Merge branch 'master' into regions

This commit is contained in:
Kishan Kavala 2013-01-31 22:31:25 +05:30
commit c607e03f0e
145 changed files with 11945 additions and 2302 deletions

View File

@ -50,7 +50,7 @@ public class FirewallRuleTO implements InternalIdentity {
FirewallRule.Purpose purpose; FirewallRule.Purpose purpose;
private Integer icmpType; private Integer icmpType;
private Integer icmpCode; private Integer icmpCode;
private FirewallRule.TrafficType trafficType;
protected FirewallRuleTO() { protected FirewallRuleTO() {
} }
@ -85,6 +85,7 @@ public class FirewallRuleTO implements InternalIdentity {
this.sourceCidrList = sourceCidr; this.sourceCidrList = sourceCidr;
this.icmpType = icmpType; this.icmpType = icmpType;
this.icmpCode = icmpCode; this.icmpCode = icmpCode;
this.trafficType = null;
} }
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp) { public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode()); this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
@ -94,6 +95,23 @@ public class FirewallRuleTO implements InternalIdentity {
this(rule.getId(),null, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode()); this(rule.getId(),null, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
} }
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
this.trafficType = trafficType;
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, boolean revokeState, boolean alreadyAdded) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), revokeState, alreadyAdded, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public FirewallRule.TrafficType getTrafficType(){
return trafficType;
}
public long getId() { public long getId() {
return id; return id;
} }

View File

@ -26,6 +26,7 @@ public class EventTypes {
public static final String EVENT_VM_UPDATE = "VM.UPDATE"; public static final String EVENT_VM_UPDATE = "VM.UPDATE";
public static final String EVENT_VM_UPGRADE = "VM.UPGRADE"; public static final String EVENT_VM_UPGRADE = "VM.UPGRADE";
public static final String EVENT_VM_RESETPASSWORD = "VM.RESETPASSWORD"; public static final String EVENT_VM_RESETPASSWORD = "VM.RESETPASSWORD";
public static final String EVENT_VM_RESETSSHKEY = "VM.RESETSSHKEY";
public static final String EVENT_VM_MIGRATE = "VM.MIGRATE"; public static final String EVENT_VM_MIGRATE = "VM.MIGRATE";
public static final String EVENT_VM_MOVE = "VM.MOVE"; public static final String EVENT_VM_MOVE = "VM.MOVE";
public static final String EVENT_VM_RESTORE = "VM.RESTORE"; public static final String EVENT_VM_RESTORE = "VM.RESTORE";
@ -63,6 +64,11 @@ public class EventTypes {
public static final String EVENT_FIREWALL_OPEN = "FIREWALL.OPEN"; public static final String EVENT_FIREWALL_OPEN = "FIREWALL.OPEN";
public static final String EVENT_FIREWALL_CLOSE = "FIREWALL.CLOSE"; public static final String EVENT_FIREWALL_CLOSE = "FIREWALL.CLOSE";
//NIC Events
public static final String EVENT_NIC_CREATE = "NIC.CREATE";
public static final String EVENT_NIC_DELETE = "NIC.DELETE";
public static final String EVENT_NIC_UPDATE = "NIC.UPDATE";
// Load Balancers // Load Balancers
public static final String EVENT_ASSIGN_TO_LOAD_BALANCER_RULE = "LB.ASSIGN.TO.RULE"; public static final String EVENT_ASSIGN_TO_LOAD_BALANCER_RULE = "LB.ASSIGN.TO.RULE";
public static final String EVENT_REMOVE_FROM_LOAD_BALANCER_RULE = "LB.REMOVE.FROM.RULE"; public static final String EVENT_REMOVE_FROM_LOAD_BALANCER_RULE = "LB.REMOVE.FROM.RULE";
@ -313,4 +319,10 @@ public class EventTypes {
public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE"; public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE";
public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE"; public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE";
public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE"; public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE";
public static final String EVENT_BAREMETAL_DHCP_SERVER_ADD = "PHYSICAL.DHCP.ADD";
public static final String EVENT_BAREMETAL_DHCP_SERVER_DELETE = "PHYSICAL.DHCP.DELETE";
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD";
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE";
} }

View File

@ -39,6 +39,8 @@ public interface Host extends StateObject<Status>, Identity, InternalIdentity {
ExternalLoadBalancer(false), ExternalLoadBalancer(false),
ExternalVirtualSwitchSupervisor(false), ExternalVirtualSwitchSupervisor(false),
PxeServer(false), PxeServer(false),
BaremetalPxe(false),
BaremetalDhcp(false),
TrafficMonitor(false), TrafficMonitor(false),
ExternalDhcp(false), ExternalDhcp(false),

View File

@ -48,7 +48,7 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification); public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
public static final Service Gateway = new Service("Gateway"); public static final Service Gateway = new Service("Gateway");
public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols, public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols,
Capability.MultipleIps, Capability.TrafficStatistics); Capability.MultipleIps, Capability.TrafficStatistics, Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation, public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation,
Capability.SupportedProtocols, Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps, Capability.SupportedProtocols, Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps,
Capability.SupportedStickinessMethods, Capability.ElasticLb); Capability.SupportedStickinessMethods, Capability.ElasticLb);
@ -173,6 +173,8 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
public static final Capability ElasticLb = new Capability("ElasticLb"); public static final Capability ElasticLb = new Capability("ElasticLb");
public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters"); public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters");
public static final Capability InlineMode = new Capability("InlineMode"); public static final Capability InlineMode = new Capability("InlineMode");
public static final Capability SupportedTrafficDirection = new Capability("SupportedTrafficDirection");
public static final Capability SupportedEgressProtocols = new Capability("SupportedEgressProtocols");
private String name; private String name;
@ -287,6 +289,8 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
void setPhysicalNetworkId(Long physicalNetworkId); void setPhysicalNetworkId(Long physicalNetworkId);
public void setTrafficType(TrafficType type);
ACLType getAclType(); ACLType getAclType();
boolean isRestartRequired(); boolean isRestartRequired();

View File

@ -226,4 +226,8 @@ public class NetworkProfile implements Network {
return vpcId; return vpcId;
} }
@Override
public void setTrafficType(TrafficType type) {
this.trafficType = type;
}
} }

View File

@ -30,4 +30,5 @@ public interface UserDataServiceProvider extends NetworkElement {
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException;
boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException; boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException;
boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException; boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException;
boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, String SSHPublicKey) throws ResourceUnavailableException;
} }

View File

@ -27,7 +27,8 @@ import com.cloud.user.Account;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
public interface FirewallService { public interface FirewallService {
FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException; FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
FirewallRule createEgressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd); Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd);
@ -40,7 +41,8 @@ public interface FirewallService {
*/ */
boolean revokeFirewallRule(long ruleId, boolean apply); boolean revokeFirewallRule(long ruleId, boolean apply);
boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException; boolean applyEgressFirewallRules (FirewallRule rule, Account caller) throws ResourceUnavailableException;
boolean applyIngressFirewallRules(long Ipid , Account caller) throws ResourceUnavailableException;
FirewallRule getFirewallRule(long ruleId); FirewallRule getFirewallRule(long ruleId);

View File

@ -33,6 +33,7 @@ import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd; import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd; import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd;
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd; import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
@ -88,6 +89,15 @@ public interface UserVmService {
*/ */
UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException; UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException;
/**
* Resets the SSH Key of a virtual machine.
*
* @param cmd
* - the command specifying vmId, Keypair name
* @return the VM if reset worked successfully, null otherwise
*/
UserVm resetVMSSHKey(ResetVMSSHKeyCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException;
/** /**
* Attaches the specified volume to the specified VM * Attaches the specified volume to the specified VM
* *
@ -113,6 +123,27 @@ public interface UserVmService {
UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException; UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException;
/**
* Adds a NIC on the given network to the virtual machine
* @param cmd the command object that defines the vm and the given network
* @return the vm object if successful, null otherwise
*/
UserVm addNicToVirtualMachine(AddNicToVMCmd cmd);
/**
* Removes a NIC on the given network from the virtual machine
* @param cmd the command object that defines the vm and the given network
* @return the vm object if successful, null otherwise
*/
UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd);
/**
* Updates default Nic to the given network for given virtual machine
* @param cmd the command object that defines the vm and the given network
* @return the vm object if successful, null otherwise
*/
UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd);
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException; UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
/** /**

2
api/src/org/apache/cloudstack/api/ApiConstants.java Normal file → Executable file
View File

@ -224,6 +224,7 @@ public class ApiConstants {
public static final String NETWORK_OFFERING_ID = "networkofferingid"; public static final String NETWORK_OFFERING_ID = "networkofferingid";
public static final String NETWORK_IDS = "networkids"; public static final String NETWORK_IDS = "networkids";
public static final String NETWORK_ID = "networkid"; public static final String NETWORK_ID = "networkid";
public static final String NIC_ID = "nicid";
public static final String SPECIFY_VLAN = "specifyvlan"; public static final String SPECIFY_VLAN = "specifyvlan";
public static final String IS_DEFAULT = "isdefault"; public static final String IS_DEFAULT = "isdefault";
public static final String IS_SYSTEM = "issystem"; public static final String IS_SYSTEM = "issystem";
@ -430,6 +431,7 @@ public class ApiConstants {
public static final String CONDITION_IDS = "conditionids"; public static final String CONDITION_IDS = "conditionids";
public static final String COUNTERPARAM_LIST = "counterparam"; public static final String COUNTERPARAM_LIST = "counterparam";
public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; public static final String AUTOSCALE_USER_ID = "autoscaleuserid";
public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
public enum HostDetails { public enum HostDetails {
all, capacity, events, stats, min; all, capacity, events, stats, min;

View File

@ -292,14 +292,14 @@ public abstract class BaseCmd {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
// JSON response // JSON response
sb.append("{ \"" + getCommandName() + "\" : { " + "\"@attributes\":{\"cloudstack-version\":\"" + _mgr.getVersion() + "\"},"); sb.append("{ \"" + getCommandName() + "\" : { " + "\"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},");
sb.append("\"errorcode\" : \"" + apiException.getErrorCode() + "\", \"description\" : \"" + apiException.getDescription() + "\" } }"); sb.append("\"errorcode\" : \"" + apiException.getErrorCode() + "\", \"description\" : \"" + apiException.getDescription() + "\" } }");
} else { } else {
sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
sb.append("<" + getCommandName() + ">"); sb.append("<" + getCommandName() + ">");
sb.append("<errorcode>" + apiException.getErrorCode() + "</errorcode>"); sb.append("<errorcode>" + apiException.getErrorCode() + "</errorcode>");
sb.append("<description>" + escapeXml(apiException.getDescription()) + "</description>"); sb.append("<description>" + escapeXml(apiException.getDescription()) + "</description>");
sb.append("</" + getCommandName() + " cloudstack-version=\"" + _mgr.getVersion() + "\">"); sb.append("</" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">");
} }
return sb.toString(); return sb.toString();
} }
@ -310,10 +310,10 @@ public abstract class BaseCmd {
// set up the return value with the name of the response // set up the return value with the name of the response
if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
prefixSb.append("{ \"" + getCommandName() + "\" : { \"@attributes\":{\"cloudstack-version\":\"" + _mgr.getVersion() + "\"},"); prefixSb.append("{ \"" + getCommandName() + "\" : { \"@attributes\":{\"cloud-stack-version\":\"" + _mgr.getVersion() + "\"},");
} else { } else {
prefixSb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"); prefixSb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
prefixSb.append("<" + getCommandName() + " cloudstack-version=\"" + _mgr.getVersion() + "\">"); prefixSb.append("<" + getCommandName() + " cloud-stack-version=\"" + _mgr.getVersion() + "\">");
} }
int i = 0; int i = 0;

View File

@ -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.package org.apache.cloudstack.api.command.user.firewall;
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.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.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.net.NetUtils;
@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class)
public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule {
public static final Logger s_logger = Logger.getLogger(CreateEgressFirewallRuleCmd.class.getName());
private static final String s_name = "createegressfirewallruleresponse";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter (name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "the network id of the port forwarding rule")
private Long networkId;
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.")
private String protocol;
@Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of firewall rule")
private Integer publicStartPort;
@Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "the ending port of firewall rule")
private Integer publicEndPort;
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
private List<String> cidrlist;
@Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
private Integer icmpType;
@Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message")
private Integer icmpCode;
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "type of firewallrule: system/user")
private String type;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public Long getIpAddressId() {
return null;
}
@Override
public String getProtocol() {
return protocol.trim();
}
@Override
public List<String> getSourceCidrList() {
if (cidrlist != null) {
return cidrlist;
} else {
List<String> oneCidrList = new ArrayList<String>();
oneCidrList.add(_networkService.getNetwork(networkId).getCidr());
return oneCidrList;
}
}
public Long getVpcId() {
Network network = _networkService.getNetwork(getNetworkId());
if (network == null) {
throw new InvalidParameterValueException("Invalid networkId is given");
}
Long vpcId = network.getVpcId();
return vpcId;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public void setSourceCidrList(List<String> cidrs){
cidrlist = cidrs;
}
@Override
public void execute() throws ResourceUnavailableException {
UserContext callerContext = UserContext.current();
boolean success = false;
FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
success = _firewallService.applyEgressFirewallRules (rule, callerContext.getCaller());
// State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(FirewallRule.class, getEntityId());
FirewallResponse fwResponse = new FirewallResponse();
if (rule != null) {
fwResponse = _responseGenerator.createFirewallResponse(rule);
setResponseObject(fwResponse);
}
fwResponse.setResponseName(getCommandName());
} finally {
if (!success || rule == null) {
_firewallService.revokeFirewallRule(getEntityId(), true);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create firewall rule");
}
}
}
@Override
public long getId() {
throw new UnsupportedOperationException("database id can only provided by VO objects");
}
@Override
public String getXid() {
// FIXME: We should allow for end user to specify Xid.
return null;
}
@Override
public Long getSourceIpAddressId() {
return null;
}
@Override
public Integer getSourcePortStart() {
if (publicStartPort != null) {
return publicStartPort.intValue();
}
return null;
}
@Override
public Integer getSourcePortEnd() {
if (publicEndPort == null) {
if (publicStartPort != null) {
return publicStartPort.intValue();
}
} else {
return publicEndPort.intValue();
}
return null;
}
@Override
public Purpose getPurpose() {
return Purpose.Firewall;
}
@Override
public State getState() {
throw new UnsupportedOperationException("Should never call me to find the state");
}
@Override
public long getNetworkId() {
return networkId;
}
@Override
public long getEntityOwnerId() {
Account account = UserContext.current().getCaller();
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public long getDomainId() {
Network network =_networkService.getNetwork(networkId);
return network.getDomainId();
}
@Override
public void create() {
if (getSourceCidrList() != null) {
String guestCidr = _networkService.getNetwork(getNetworkId()).getCidr();
for (String cidr: getSourceCidrList()){
if (!NetUtils.isValidCIDR(cidr)){
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr);
}
if (cidr.equals(NetUtils.ALL_CIDRS)) {
continue;
}
if(!NetUtils.isNetworkAWithinNetworkB(cidr, guestCidr)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, cidr + "is not within the guest cidr " + guestCidr);
}
}
}
if (getProtocol().equalsIgnoreCase(NetUtils.ALL_PROTO)) {
if (getSourcePortStart() != null && getSourcePortEnd() != null) {
throw new InvalidParameterValueException("Do not pass ports to protocol ALL, porotocol ALL do not require ports. Unable to create "
+"firewall rule for the network id=" + networkId);
}
}
if (getVpcId() != null ){
throw new InvalidParameterValueException("Unable to create firewall rule for the network id=" + networkId +
" as firewall egress rule can be created only for non vpc networks.");
}
try {
FirewallRule result = _firewallService.createEgressFirewallRule(this);
setEntityId(result.getId());
} catch (NetworkRuleConflictException ex) {
s_logger.info("Network rule conflict: " + ex.getMessage());
s_logger.trace("Network Rule Conflict: ", ex);
throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
}
}
@Override
public String getEventType() {
return EventTypes.EVENT_FIREWALL_OPEN;
}
@Override
public String getEventDescription() {
Network network = _networkService.getNetwork(networkId);
return ("Creating firewall rule for network: " + network + " for protocol:" + this.getProtocol());
}
@Override
public long getAccountId() {
Network network = _networkService.getNetwork(networkId);
return network.getAccountId();
}
@Override
public String getSyncObjType() {
return BaseAsyncCmd.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return getNetworkId();
}
@Override
public Integer getIcmpCode() {
if (icmpCode != null) {
return icmpCode;
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
return -1;
}
return null;
}
@Override
public Integer getIcmpType() {
if (icmpType != null) {
return icmpType;
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
return -1;
}
return null;
}
@Override
public Long getRelated() {
return null;
}
@Override
public FirewallRuleType getType() {
if (type != null && type.equalsIgnoreCase("system")) {
return FirewallRuleType.System;
} else {
return FirewallRuleType.User;
}
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.FirewallRule;
}
@Override
public TrafficType getTrafficType() {
return TrafficType.Egress;
}
@Override
public String getUuid() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -122,7 +122,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId()); FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
try { try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId()); UserContext.current().setEventDetails("Rule Id: " + getEntityId());
success = _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller()); success = _firewallService.applyIngressFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
// State is different after the rule is applied, so get new object here // State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(FirewallRule.class, getEntityId()); rule = _entityMgr.findById(FirewallRule.class, getEntityId());
@ -238,7 +238,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
} }
try { try {
FirewallRule result = _firewallService.createFirewallRule(this); FirewallRule result = _firewallService.createIngressFirewallRule(this);
setEntityId(result.getId()); setEntityId(result.getId());
setEntityUuid(result.getUuid()); setEntityUuid(result.getUuid());
} catch (NetworkRuleConflictException ex) { } catch (NetworkRuleConflictException ex) {

View File

@ -163,7 +163,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
UserContext.current().setEventDetails("Rule Id: " + getEntityId()); UserContext.current().setEventDetails("Rule Id: " + getEntityId());
if (getOpenFirewall()) { if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(ipAddressId, callerContext.getCaller()); success = success && _firewallService.applyIngressFirewallRules(ipAddressId, callerContext.getCaller());
} }
success = success && _rulesService.applyPortForwardingRules(ipAddressId, callerContext.getCaller()); success = success && _rulesService.applyPortForwardingRules(ipAddressId, callerContext.getCaller());

View File

@ -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.api.command.user.firewall;
package org.apache.cloudstack.api.command.user.firewall;
import org.apache.cloudstack.api.APICommand;
import org.apache.log4j.Logger;
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.ServerApiException;
import org.apache.cloudstack.api.response.SuccessResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.rules.FirewallRule;
import com.cloud.user.UserContext;
@APICommand(name = "deleteEgressFirewallRule", description="Deletes an ggress firewall rule", responseObject=SuccessResponse.class)
public class DeleteEgressFirewallRuleCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteEgressFirewallRuleCmd.class.getName());
private static final String s_name = "deleteegressfirewallruleresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the firewall rule")
private Long id;
// unexposed parameter needed for events logging
@Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.LONG, expose=false)
private Long ownerId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public String getEventType() {
return EventTypes.EVENT_FIREWALL_CLOSE;
}
@Override
public String getEventDescription() {
return ("Deleting egress firewall rule id=" + id);
}
@Override
public long getEntityOwnerId() {
if (ownerId == null) {
FirewallRule rule = _entityMgr.findById(FirewallRule.class, id);
if (rule == null) {
throw new InvalidParameterValueException("Unable to find egress firewall rule by id");
} else {
ownerId = _entityMgr.findById(FirewallRule.class, id).getAccountId();
}
}
return ownerId;
}
@Override
public void execute() throws ResourceUnavailableException {
UserContext.current().setEventDetails("Rule Id: " + id);
boolean result = _firewallService.revokeFirewallRule(id, true);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete egress firewall rule");
}
}
@Override
public String getSyncObjType() {
return BaseAsyncCmd.networkSyncObject;
}
@Override
public Long getSyncObjId() {
return _firewallService.getFirewallRule(id).getNetworkId();
}
@Override
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.FirewallRule;
}
}

View File

@ -0,0 +1,89 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.package org.apache.cloudstack.api.command.user.firewall;
package org.apache.cloudstack.api.command.user.firewall;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.ListResponse;
import com.cloud.network.rules.FirewallRule;
import com.cloud.utils.Pair;
@APICommand(name = "listEgressFirewallRules", description="Lists all egress firewall rules for network id.", responseObject=FirewallResponse.class)
public class ListEgressFirewallRulesCmd extends ListFirewallRulesCmd {
public static final Logger s_logger = Logger.getLogger(ListEgressFirewallRulesCmd.class.getName());
private static final String s_name = "listegressfirewallrulesresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="Lists rule with the specified ID.")
private Long id;
@Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="the id network network for the egress firwall services")
private Long networkId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getNetworkId() {
return networkId;
}
public FirewallRule.TrafficType getTrafficType () {
return FirewallRule.TrafficType.Egress;
}
public Long getId() {
return id;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute(){
Pair<List<? extends FirewallRule>, Integer> result = _firewallService.listFirewallRules(this);
ListResponse<FirewallResponse> response = new ListResponse<FirewallResponse>();
List<FirewallResponse> fwResponses = new ArrayList<FirewallResponse>();
for (FirewallRule fwRule : result.first()) {
FirewallResponse ruleData = _responseGenerator.createFirewallResponse(fwRule);
ruleData.setObjectName("firewallrule");
fwResponses.add(ruleData);
}
response.setResponses(fwResponses, result.second());
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -56,6 +56,10 @@ public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd {
return ipAddressId; return ipAddressId;
} }
public FirewallRule.TrafficType getTrafficType () {
return FirewallRule.TrafficType.Ingress;
}
public Long getId() { public Long getId() {
return id; return id;
} }

View File

@ -245,7 +245,7 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements
UserContext.current().setEventDetails("Rule Id: " + getEntityId()); UserContext.current().setEventDetails("Rule Id: " + getEntityId());
if (getOpenFirewall()) { if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(getSourceIpAddressId(), callerContext.getCaller()); success = success && _firewallService.applyIngressFirewallRules(getSourceIpAddressId(), callerContext.getCaller());
} }
// State might be different after the rule is applied, so get new object here // State might be different after the rule is applied, so get new object here

View File

@ -115,7 +115,7 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
UserContext.current().setEventDetails("Rule Id: "+ getEntityId()); UserContext.current().setEventDetails("Rule Id: "+ getEntityId());
if (getOpenFirewall()) { if (getOpenFirewall()) {
result = result && _firewallService.applyFirewallRules(ipAddressId, UserContext.current().getCaller()); result = result && _firewallService.applyIngressFirewallRules(ipAddressId, UserContext.current().getCaller());
} }
result = result && _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller()); result = result && _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller());

View File

@ -0,0 +1,121 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT 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 java.util.ArrayList;
import java.util.EnumSet;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.*;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
@APICommand(name = "addNicToVirtualMachine", description="Adds VM to specified network by creating a NIC", responseObject=UserVmResponse.class)
public class AddNicToVMCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(AddNicToVMCmd.class);
private static final String s_name = "addnictovirtualmachineresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
required=true, description="Virtual Machine ID")
private Long vmId;
@Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType=NetworkResponse.class,
required=true, description="Network ID")
private Long netId;
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="IP Address for the new network")
private String ipaddr;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getVmId() {
return vmId;
}
public Long getNetworkId() {
return netId;
}
public String getIpAddress() {
return ipaddr;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_CREATE;
}
@Override
public String getEventDescription() {
return "Adding network " + getNetworkId() + " to user vm: " + getVmId();
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmById(getVmId());
if (vm == null) {
return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
}
return vm.getAccountId();
}
@Override
public void execute(){
UserContext.current().setEventDetails("Vm Id: " + getVmId() + " Network Id: " + getNetworkId());
UserVm result = _userVmService.addNicToVirtualMachine(this);
ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
dc.add(VMDetails.valueOf("nics"));
EnumSet<VMDetails> details = EnumSet.copyOf(dc);
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add NIC to vm. Refer to server logs for details.");
}
}
}

View File

@ -0,0 +1,115 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT 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 java.util.ArrayList;
import java.util.EnumSet;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.*;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.NicResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
@APICommand(name = "removeNicFromVirtualMachine", description="Removes VM from specified network by deleting a NIC", responseObject=UserVmResponse.class)
public class RemoveNicFromVMCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(RemoveNicFromVMCmd.class);
private static final String s_name = "removenicfromvirtualmachineresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
required=true, description="Virtual Machine ID")
private Long vmId;
@Parameter(name=ApiConstants.NIC_ID, type=CommandType.UUID, entityType=NicResponse.class,
required=true, description="NIC ID")
private Long nicId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getVmId() {
return vmId;
}
public Long getNicId() {
return nicId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_DELETE;
}
@Override
public String getEventDescription() {
return "Removing NIC " + getNicId() + " from user vm: " + getVmId();
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmById(getVmId());
if (vm == null) {
return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
}
return vm.getAccountId();
}
@Override
public void execute(){
UserContext.current().setEventDetails("Vm Id: "+getVmId() + " Nic Id: " + getNicId());
UserVm result = _userVmService.removeNicFromVirtualMachine(this);
ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
dc.add(VMDetails.valueOf("nics"));
EnumSet<VMDetails> details = EnumSet.copyOf(dc);
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove NIC from vm, see error log for details");
}
}
}

View File

@ -0,0 +1,151 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT 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.log4j.Logger;
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.APICommand;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import com.cloud.async.AsyncJob;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
@APICommand(name = "resetSSHKeyForVirtualMachine", responseObject = UserVmResponse.class, description = "Resets the SSH Key for virtual machine. " +
"The virtual machine must be in a \"Stopped\" state. [async]")
public class ResetVMSSHKeyCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(ResetVMSSHKeyCmd.class.getName());
private static final String s_name = "resetSSHKeyforvirtualmachineresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, description = "The ID of the virtual machine")
private Long id;
@Parameter(name = ApiConstants.SSH_KEYPAIR, type = CommandType.STRING, required = true, description = "name of the ssh key pair used to login to the virtual machine")
private String name;
//Owner information
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the ssh key. Must be used with domainId.")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used.")
private Long domainId;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the ssh key")
private Long projectId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public Long getId() {
return id;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getProjectId() {
return projectId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getEventType() {
return EventTypes.EVENT_VM_RESETSSHKEY;
}
@Override
public String getEventDescription() {
return "resetting SSHKey for vm: " + getId();
}
public AsyncJob.Type getInstanceType() {
return AsyncJob.Type.VirtualMachine;
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmById(getId());
if (vm != null) {
return vm.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
public Long getInstanceId() {
return getId();
}
@Override
public void execute() throws ResourceUnavailableException,
InsufficientCapacityException {
UserContext.current().setEventDetails("Vm Id: " + getId());
UserVm result = _userVmService.resetVMSSHKey(this);
if (result != null) {
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to reset vm SSHKey");
}
}
}

View File

@ -0,0 +1,115 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT 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 java.util.ArrayList;
import java.util.EnumSet;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.*;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.NicResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
@APICommand(name = "updateDefaultNicForVirtualMachine", description="Changes the default NIC on a VM", responseObject=UserVmResponse.class)
public class UpdateDefaultNicForVMCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(UpdateDefaultNicForVMCmd.class);
private static final String s_name = "updatedefaultnicforvirtualmachineresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
required=true, description="Virtual Machine ID")
private Long vmId;
@Parameter(name=ApiConstants.NIC_ID, type=CommandType.UUID, entityType=NicResponse.class,
required=true, description="NIC ID")
private Long nicId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getVmId() {
return vmId;
}
public Long getNicId() {
return nicId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
public static String getResultObjectName() {
return "virtualmachine";
}
@Override
public String getEventType() {
return EventTypes.EVENT_NIC_UPDATE;
}
@Override
public String getEventDescription() {
return "Updating NIC " + getNicId() + " on user vm: " + getVmId();
}
@Override
public long getEntityOwnerId() {
UserVm vm = _responseGenerator.findUserVmById(getVmId());
if (vm == null) {
return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
}
return vm.getAccountId();
}
@Override
public void execute(){
UserContext.current().setEventDetails("Vm Id: "+getVmId() + " Nic Id: " + getNicId());
UserVm result = _userVmService.updateDefaultNicForVirtualMachine(this);
ArrayList<VMDetails> dc = new ArrayList<VMDetails>();
dc.add(VMDetails.valueOf("nics"));
EnumSet<VMDetails> details = EnumSet.copyOf(dc);
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to set default nic for VM. Refer to server logs for details.");
}
}
}

View File

@ -40,6 +40,9 @@ public class FirewallResponse extends BaseResponse {
@SerializedName(ApiConstants.IP_ADDRESS_ID) @Param(description="the public ip address id for the firewall rule") @SerializedName(ApiConstants.IP_ADDRESS_ID) @Param(description="the public ip address id for the firewall rule")
private Long publicIpAddressId; private Long publicIpAddressId;
@SerializedName(ApiConstants.NETWORK_ID) @Param(description="the network id of the firewall rule")
private Long networkId;
@SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the public ip address for the firewall rule") @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the public ip address for the firewall rule")
private String publicIpAddress; private String publicIpAddress;
@ -82,6 +85,10 @@ public class FirewallResponse extends BaseResponse {
this.publicIpAddress = publicIpAddress; this.publicIpAddress = publicIpAddress;
} }
public void setNetworkId(Long networkId) {
this.networkId = networkId;
}
public void setState(String state) { public void setState(String state) {
this.state = state; this.state = state;
} }

View File

@ -17,11 +17,14 @@
package org.apache.cloudstack.api.response; package org.apache.cloudstack.api.response;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import com.cloud.vm.Nic;
import com.cloud.serializer.Param; import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@EntityReference(value=Nic.class)
public class NicResponse extends BaseResponse { public class NicResponse extends BaseResponse {
@SerializedName("id") @Param(description="the ID of the nic") @SerializedName("id") @Param(description="the ID of the nic")

View File

@ -1215,6 +1215,7 @@ label.network.offering.id=Network Offering ID
label.network.offering.name=Network Offering Name label.network.offering.name=Network Offering Name
label.network.offering=Network Offering label.network.offering=Network Offering
label.network.rate=Network Rate label.network.rate=Network Rate
label.network.rate.megabytes=Network Rate (Mb/s)
label.network.read=Network Read label.network.read=Network Read
label.network.type=Network Type label.network.type=Network Type
label.network.write=Network Write label.network.write=Network Write

View File

@ -60,6 +60,7 @@ rebootVirtualMachine=15
startVirtualMachine=15 startVirtualMachine=15
stopVirtualMachine=15 stopVirtualMachine=15
resetPasswordForVirtualMachine=15 resetPasswordForVirtualMachine=15
resetSSHKeyForVirtualMachine=15
updateVirtualMachine=15 updateVirtualMachine=15
listVirtualMachines=15 listVirtualMachines=15
getVMPassword=15 getVMPassword=15
@ -320,6 +321,11 @@ listNetworks=15
restartNetwork=15 restartNetwork=15
updateNetwork=15 updateNetwork=15
#### nic commands ####
addNicToVirtualMachine=15
removeNicFromVirtualMachine=15
updateDefaultNicForVirtualMachine=15
#### SSH key pair commands #### SSH key pair commands
registerSSHKeyPair=15 registerSSHKeyPair=15
createSSHKeyPair=15 createSSHKeyPair=15
@ -345,6 +351,11 @@ createFirewallRule=15
deleteFirewallRule=15 deleteFirewallRule=15
listFirewallRules=15 listFirewallRules=15
####
createEgressFirewallRule=15
deleteEgressFirewallRule=15
listEgressFirewallRules=15
#### hypervisor capabilities commands #### hypervisor capabilities commands
updateHypervisorCapabilities=1 updateHypervisorCapabilities=1
listHypervisorCapabilities=1 listHypervisorCapabilities=1

View File

@ -197,7 +197,6 @@
<!-- Listen on 6443 instead of 8443 because tomcat6 will change 8443 to a random one when CATALINA_HOME is not /usr/share/tomcat6 --> <!-- Listen on 6443 instead of 8443 because tomcat6 will change 8443 to a random one when CATALINA_HOME is not /usr/share/tomcat6 -->
<Connector executor="tomcatThreadPool-internal" port="5443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" <Connector executor="tomcatThreadPool-internal" port="5443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
>>>>>>> bcfd64a... CS-15373: Awsapi port change to 7080.
maxThreads="150" scheme="https" secure="true" maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" clientAuth="false" sslProtocol="TLS"
keystoreType="JKS" keystoreType="JKS"

View File

@ -69,12 +69,14 @@ import com.cloud.agent.api.routing.SetStaticRouteCommand;
import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand;
import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.agent.api.to.StaticNatRuleTO;
import com.cloud.exception.InternalErrorException; import com.cloud.exception.InternalErrorException;
import com.cloud.network.HAProxyConfigurator; import com.cloud.network.HAProxyConfigurator;
import com.cloud.network.LoadBalancerConfigurator; import com.cloud.network.LoadBalancerConfigurator;
import com.cloud.network.rules.FirewallRule;
import com.cloud.utils.NumbersUtil; import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Manager; import com.cloud.utils.component.Manager;
import com.cloud.utils.net.NetUtils; import com.cloud.utils.net.NetUtils;
@ -214,11 +216,18 @@ public class VirtualRoutingResource implements Manager {
return new SetFirewallRulesAnswer(cmd, false, results); return new SetFirewallRulesAnswer(cmd, false, results);
} }
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
String[][] rules = cmd.generateFwRules(); String[][] rules = cmd.generateFwRules();
final Script command = new Script(_firewallPath, _timeout, s_logger); final Script command = new Script(_firewallPath, _timeout, s_logger);
command.add(routerIp); command.add(routerIp);
command.add("-F"); command.add("-F");
if (trafficType == FirewallRule.TrafficType.Egress){
command.add("-E");
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0]; String[] fwRules = rules[0];
if (fwRules.length > 0) { if (fwRules.length > 0) {

View File

@ -24,7 +24,12 @@
<section id="about-security-groups"> <section id="about-security-groups">
<title>About Security Groups</title> <title>About Security Groups</title>
<para>Security groups provide a way to isolate traffic to VMs. A security group is a group of VMs that filter their incoming and outgoing traffic according to a set of rules, called ingress and egress rules. These rules filter network traffic according to the IP address that is attempting to communicate with the VM. Security groups are particularly useful in zones that use basic networking, because there is a single guest network for all guest VMs. In &PRODUCT; 3.0.3 - 3.0.5, security groups are supported only in zones that use basic networking.</para> <para>Security groups provide a way to isolate traffic to VMs. A security group is a group of
VMs that filter their incoming and outgoing traffic according to a set of rules, called
ingress and egress rules. These rules filter network traffic according to the IP address
that is attempting to communicate with the VM. Security groups are particularly useful in
zones that use basic networking, because there is a single guest network for all guest VMs.
In advanced zones, security groups are supported only on the KVM hypervisor.</para>
<note><para>In a zone that uses advanced networking, you can instead define multiple guest networks to isolate traffic to VMs.</para> <note><para>In a zone that uses advanced networking, you can instead define multiple guest networks to isolate traffic to VMs.</para>
</note> </note>
<para></para> <para></para>

View File

@ -32,5 +32,4 @@
<listitem><para>The Management Server loses heartbeat from a Host for more than 3 minutes</para></listitem> <listitem><para>The Management Server loses heartbeat from a Host for more than 3 minutes</para></listitem>
<listitem><para>The Host cluster runs low on CPU, memory, or storage resources</para></listitem> <listitem><para>The Host cluster runs low on CPU, memory, or storage resources</para></listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View File

@ -31,7 +31,7 @@
<para>Set the following paramaters:</para> <para>Set the following paramaters:</para>
<programlisting>listen_tls = 0</programlisting> <programlisting>listen_tls = 0</programlisting>
<programlisting>listen_tcp = 1</programlisting> <programlisting>listen_tcp = 1</programlisting>
<programlisting>tcp_port = 16059</programlisting> <programlisting>tcp_port = "16059"</programlisting>
<programlisting>auth_tcp = "none"</programlisting> <programlisting>auth_tcp = "none"</programlisting>
<programlisting>mdns_adv = 0</programlisting> <programlisting>mdns_adv = 0</programlisting>
</listitem> </listitem>

View File

@ -0,0 +1,52 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<section id="security-groups-advanced-zones">
<title>Security Groups in Advanced Zones (KVM Only)</title>
<para>&PRODUCT; provides the ability to use security groups to provide isolation between
guests on a single shared, zone-wide network in an advanced zone where KVM is the
hypervisor. Using security groups in advanced zones rather than multiple VLANs allows a greater range
of options for setting up guest isolation in a cloud.</para>
<formalpara>
<title>Limitations</title>
<para>The following are not supported for this feature:</para>
</formalpara>
<itemizedlist>
<listitem>
<para>Two IP ranges with the same VLAN and different gateway or netmask in security
group-enabled shared network.</para>
</listitem>
<listitem>
<para>Two IP ranges with the same VLAN and different gateway or netmask in
account-specific shared networks.</para>
</listitem>
<listitem>
<para>Multiple VLAN ranges in security group-enabled shared network.</para>
</listitem>
<listitem>
<para>Multiple VLAN ranges in account-specific shared networks.</para>
</listitem>
</itemizedlist>
<para>Security groups must be enabled in the zone in order for this feature to be used.</para>
</section>

View File

@ -25,7 +25,8 @@
<section id="security-groups"> <section id="security-groups">
<title>Security Groups</title> <title>Security Groups</title>
<xi:include href="about-security-groups.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="about-security-groups.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="add-security-group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="security-groups-advanced-zones.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="enable-security-groups.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="enable-security-groups.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="add-security-group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="add-ingress-egress-rules.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="add-ingress-egress-rules.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</section> </section>

View File

@ -0,0 +1,45 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "file:///C:/Program%20Files%20(x86)/Publican/DocBook_DTD/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<section id="snapshot-throttling">
<title>Snapshot Job Throttling</title>
<para>When a snapshot of a virtual machine is requested, the snapshot job runs on the same
host where the VM is running or, in the case of a stopped VM, the host where it ran last. If
many snapshots are requested for VMs on a single host, this can lead to problems with too
many snapshot jobs overwhelming the resources of the host.</para>
<para>To address this situation, the cloud's root administrator can throttle how many snapshot
jobs are executed simultaneously on the hosts in the cloud by using the global configuration
setting concurrent.snapshots.threshold.perhost. By using this setting, the administrator can
better ensure that snapshot jobs do not time out and hypervisor hosts do not experience
performance issues due to hosts being overloaded with too many snapshot requests.</para>
<para>Set concurrent.snapshots.threshold.perhost to a value that represents a best guess about
how many snapshot jobs the hypervisor hosts can execute at one time, given the current
resources of the hosts and the number of VMs running on the hosts. If a given host has more
snapshot requests, the additional requests are placed in a waiting queue. No new snapshot
jobs will start until the number of currently executing snapshot jobs falls below the
configured limit.</para>
<para>The admin can also set job.expire.minutes to place a maximum on how long a snapshot
request will wait in the queue. If this limit is reached, the snapshot request fails and
returns an error message. </para>
</section>

View File

@ -102,4 +102,11 @@ KfEEuzcCUIxtJYTahJ1pvlFkQ8anpuxjSEDp8x/18bq3
<programlisting>ssh -i ~/.ssh/keypair-doc &lt;ip address&gt;</programlisting> <programlisting>ssh -i ~/.ssh/keypair-doc &lt;ip address&gt;</programlisting>
<para>The -i parameter tells the ssh client to use a ssh key found at ~/.ssh/keypair-doc.</para> <para>The -i parameter tells the ssh client to use a ssh key found at ~/.ssh/keypair-doc.</para>
</section> </section>
<section id="reset-ssh">
<title>Resetting SSH Keys</title>
<para>With the API command resetSSHKeyForVirtualMachine, a user can set or reset the SSH keypair
assigned to a virtual machine. A lost or compromised SSH keypair
can be changed, and the user can access the VM by using the new keypair. Just create or register a
new keypair, then call resetSSHKeyForVirtualMachine.</para>
</section>
</section> </section>

View File

@ -29,4 +29,5 @@
<para>Snapshots may be taken for volumes, including both root and data disks. The administrator places a limit on the number of stored snapshots per user. Users can create new volumes from the snapshot for recovery of particular files and they can create templates from snapshots to boot from a restored disk.</para> <para>Snapshots may be taken for volumes, including both root and data disks. The administrator places a limit on the number of stored snapshots per user. Users can create new volumes from the snapshot for recovery of particular files and they can create templates from snapshots to boot from a restored disk.</para>
<para>Users can create snapshots manually or by setting up automatic recurring snapshot policies. Users can also create disk volumes from snapshots, which may be attached to a VM like any other disk volume. Snapshots of both root disks and data disks are supported. However, &PRODUCT; does not currently support booting a VM from a recovered root disk. A disk recovered from snapshot of a root disk is treated as a regular data disk; the data on recovered disk can be accessed by attaching the disk to a VM.</para> <para>Users can create snapshots manually or by setting up automatic recurring snapshot policies. Users can also create disk volumes from snapshots, which may be attached to a VM like any other disk volume. Snapshots of both root disks and data disks are supported. However, &PRODUCT; does not currently support booting a VM from a recovered root disk. A disk recovered from snapshot of a root disk is treated as a regular data disk; the data on recovered disk can be accessed by attaching the disk to a VM.</para>
<para>A completed snapshot is copied from primary storage to secondary storage, where it is stored until deleted or purged by newer snapshot.</para> <para>A completed snapshot is copied from primary storage to secondary storage, where it is stored until deleted or purged by newer snapshot.</para>
<xi:include href="snapshot-throttling.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</section> </section>

View File

@ -58,7 +58,7 @@ export JAVA_HOME
SCP="" SCP=""
DCP="" DCP=""
ACP=`ls /usr/share/cloud/java/* | tr '\n' ':'` ACP=`ls /usr/share/cloud/java/* | tr '\n' ':'`
JCP="/usr/share/java/commons-daemon.jar" JCP="/usr/share/java/jna.jar:/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath # We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods # AgentShell implements the JSVC daemon methods

138
packaging/centos63/cloud-usage.rc Executable file
View File

@ -0,0 +1,138 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: cloud usage
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: Start/stop Apache CloudStack Usage Monitor
# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor
## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used
## for storing usage statistics from instances.
## JSVC (Java daemonizing) is used for starting and stopping the usage monitor.
### END INIT INFO
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
. /etc/rc.d/init.d/functions
SHORTNAME="cloud-usage"
PIDFILE=/var/run/"$SHORTNAME".pid
LOCKFILE=/var/lock/subsys/"$SHORTNAME"
LOGFILE=/var/log/cloud/usage/usage.log
PROGNAME="CloudStack Usage Monitor"
CLASS="com.cloud.usage.UsageServer"
PROG="jsvc"
DAEMON="/usr/bin/jsvc"
USER=cloud
unset OPTIONS
[ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME"
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk"
for jdir in $JDK_DIRS; do
if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
JAVA_HOME="$jdir"
fi
done
export JAVA_HOME
SCP=""
DCP=""
UCP=`ls /usr/share/cloud/usage/java/* | tr '\n' ':'`
JCP="/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods
export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/sysconfig
start() {
if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
echo "$PROGNAME apparently already running"
exit 0
fi
if hostname --fqdn >/dev/null 2>&1 ; then
true
else
echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
exit 1
fi
echo -n "Starting $PROGNAME" "$SHORTNAME"
if daemon --pidfile $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -errfile SYSLOG -Dpid=$$ $CLASS
RETVAL=$?
then
rc=0
sleep 1
if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
failure
rc=1
fi
else
rc=1
fi
if [ $rc -eq 0 ]; then
success
else
failure
rm -f "$PIDFILE"
fi
echo
}
stop() {
echo -n "Stopping $PROGNAME" "$SHORTNAME"
killproc -p $PIDFILE $DAEMON
if [ "$?" -eq 0 ]; then
success
else
failure
fi
rm -f "$PIDFILE"
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p $PIDFILE $SHORTNAME
RETVAL=$?
;;
restart | force-reload)
stop
sleep 3
start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
RETVAL=3
esac
exit $RETVAL

View File

@ -112,10 +112,21 @@ Requires: bridge-utils
Requires: ebtables Requires: ebtables
Requires: jsvc Requires: jsvc
Requires: jna Requires: jna
Requires: jakarta-commons-daemon
Requires: jakarta-commons-daemon-jsvc
Group: System Environment/Libraries Group: System Environment/Libraries
%description agent %description agent
The CloudStack agent for KVM hypervisors The CloudStack agent for KVM hypervisors
%package usage
Summary: CloudStack Usage calculation server
Requires: java >= 1.6.0
Requires: jsvc
Requires: jakarta-commons-daemon
Requires: jakarta-commons-daemon-jsvc
%description usage
The CloudStack usage calculation service
%prep %prep
echo Doing CloudStack build echo Doing CloudStack build
@ -196,6 +207,7 @@ chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
chmod -R ugo+x ${RPM_BUILD_ROOT}/usr/share/%{name}/management/webapps/client/WEB-INF/classes/scripts chmod -R ugo+x ${RPM_BUILD_ROOT}/usr/share/%{name}/management/webapps/client/WEB-INF/classes/scripts
# KVM Agent
mkdir -p ${RPM_BUILD_ROOT}/etc/cloud/agent mkdir -p ${RPM_BUILD_ROOT}/etc/cloud/agent
mkdir -p ${RPM_BUILD_ROOT}/var/log/cloud/agent mkdir -p ${RPM_BUILD_ROOT}/var/log/cloud/agent
install -D packaging/centos63/cloud-agent.rc ${RPM_BUILD_ROOT}/etc/init.d/%{name}-agent install -D packaging/centos63/cloud-agent.rc ${RPM_BUILD_ROOT}/etc/init.d/%{name}-agent
@ -204,12 +216,17 @@ install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}/etc
install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}/etc/cloud/agent/log4j-cloud.xml install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}/etc/cloud/agent/log4j-cloud.xml
install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}/usr/bin/cloud-setup-agent install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}/usr/bin/cloud-setup-agent
install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}/usr/bin/cloud-ssh install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}/usr/bin/cloud-ssh
install -D plugins/hypervisors/kvm/target/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar ${RPM_BUILD_ROOT}/usr/share/cloud/java/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar install -D plugins/hypervisors/kvm/target/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar ${RPM_BUILD_ROOT}/usr/share/cloud/java/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar
cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}/usr/share/cloud/java cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}/usr/share/cloud/java
mkdir -p ${RPM_BUILD_ROOT}/usr/share/cloud/scripts mkdir -p ${RPM_BUILD_ROOT}/usr/share/cloud/scripts
cp -r scripts/* ${RPM_BUILD_ROOT}/usr/share/cloud/scripts cp -r scripts/* ${RPM_BUILD_ROOT}/usr/share/cloud/scripts
# Usage server
install -D usage/target/%{name}-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}/usr/share/cloud/usage/java/%{name}-usage-%{_maventag}.jar
cp usage/target/dependencies/* ${RPM_BUILD_ROOT}/usr/share/cloud/usage/java
install -D packaging/centos63/cloud-usage.rc ${RPM_BUILD_ROOT}/etc/init.d/%{name}-usage
mkdir -p ${RPM_BUILD_ROOT}/var/log/cloud/usage/
%clean %clean
[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT} [ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
@ -306,6 +323,11 @@ fi
%attr(0644,root,root) /usr/share/cloud/java/*.jar %attr(0644,root,root) /usr/share/cloud/java/*.jar
%attr(0755,root,root) /usr/share/cloud/scripts %attr(0755,root,root) /usr/share/cloud/scripts
%files usage
%attr(0755,root,root) %{_sysconfdir}/init.d/cloud-usage
%attr(0644,root,root) /usr/share/cloud/usage/java/*.jar
%dir /var/log/cloud/usage
%changelog %changelog
* Fri Oct 03 2012 Hugo Trippaers <hugo@apache.org> 4.1.0 * Fri Oct 03 2012 Hugo Trippaers <hugo@apache.org> 4.1.0
- new style spec file - new style spec file

View File

@ -24,6 +24,7 @@ COMMIT
:INPUT DROP [0:0] :INPUT DROP [0:0]
:FORWARD DROP [0:0] :FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0]
:FW_OUTBOUND - [0:0]
-A INPUT -d 224.0.0.18/32 -j ACCEPT -A INPUT -d 224.0.0.18/32 -j ACCEPT
-A INPUT -d 225.0.0.50/32 -j ACCEPT -A INPUT -d 225.0.0.50/32 -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
@ -37,10 +38,11 @@ COMMIT
-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT -A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state NEW --dport 80 -j ACCEPT -A INPUT -i eth0 -p tcp -m state --state NEW --dport 80 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth2 -j ACCEPT
-A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth0 -m state --state NEW -j ACCEPT -A FORWARD -i eth0 -o eth0 -m state --state NEW -j ACCEPT
-A FORWARD -i eth0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i eth0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth2 -j FW_OUTBOUND
-I FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT COMMIT
*mangle *mangle
:PREROUTING ACCEPT [0:0] :PREROUTING ACCEPT [0:0]

View File

@ -212,9 +212,9 @@ add_first_ip() {
ip_addr_add $ethDev $pubIp ip_addr_add $ethDev $pubIp
sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT sudo iptables -D FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
sudo iptables -A FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -A FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o $ethDev -j ACCEPT sudo iptables -A FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
add_snat $1 add_snat $1
if [ $? -gt 0 -a $? -ne 2 ] if [ $? -gt 0 -a $? -ne 2 ]
@ -246,7 +246,7 @@ remove_first_ip() {
[ "$mask" == "" ] && mask="32" [ "$mask" == "" ] && mask="32"
sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT sudo iptables -D FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
remove_snat $1 remove_snat $1
sudo ip addr del dev $ethDev "$ipNoMask/$mask" sudo ip addr del dev $ethDev "$ipNoMask/$mask"

View File

@ -0,0 +1,171 @@
#!/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
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# $Id: firewallRule_egress.sh 9947 2013-01-17 19:34:24Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/patches/xenserver/root/firewallRule_egress.sh $
# firewallRule_egress.sh -- allow some ports / protocols from vm instances
# @VERSION@
source /root/func.sh
lock="biglock"
locked=$(getLockFile $lock)
if [ "$locked" != "1" ]
then
exit 1
fi
#set -x
usage() {
printf "Usage: %s: -a protocol:startport:endport:sourcecidrs> \n" $(basename $0) >&2
printf "sourcecidrs format: cidr1-cidr2-cidr3-...\n"
}
fw_egress_remove_backup() {
sudo iptables -D FW_OUTBOUND -j _FW_EGRESS_RULES
sudo iptables -F _FW_EGRESS_RULES
sudo iptables -X _FW_EGRESS_RULES
}
fw_egress_save() {
sudo iptables -E FW_EGRESS_RULES _FW_EGRESS_RULES
}
fw_egress_chain () {
#supress errors 2>/dev/null
fw_egress_remove_backup
fw_egress_save
sudo iptables -N FW_EGRESS_RULES
sudo iptables -A FW_OUTBOUND -j FW_EGRESS_RULES
}
fw_egress_backup_restore() {
sudo iptables -A FW_OUTBOUND -j FW_EGRESS_RULES
sudo iptables -E _FW_EGRESS_RULES FW_EGRESS_RULES
fw_egress_remove_backup
}
fw_entry_for_egress() {
local rule=$1
local prot=$(echo $rule | cut -d: -f2)
local sport=$(echo $rule | cut -d: -f3)
local eport=$(echo $rule | cut -d: -f4)
local cidrs=$(echo $rule | cut -d: -f5 | sed 's/-/ /g')
if [ "$sport" == "0" -a "$eport" == "0" ]
then
DPORT=""
else
DPORT="--dport $sport:$eport"
fi
logger -t cloud "$(basename $0): enter apply fw egress rules for guest $prot:$sport:$eport:$cidrs"
for lcidr in $cidrs
do
[ "$prot" == "reverted" ] && continue;
if [ "$prot" == "icmp" ]
then
typecode="$sport/$eport"
[ "$eport" == "-1" ] && typecode="$sport"
[ "$sport" == "-1" ] && typecode="any"
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr --icmp-type $typecode \
-j ACCEPT
result=$?
elif [ "$prot" == "all" ]
then
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr -j ACCEPT
result=$?
else
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr \
$DPORT -j ACCEPT
result=$?
fi
[ $result -gt 0 ] &&
logger -t cloud "Error adding iptables entry for guest network $prot:$sport:$eport:$cidrs" &&
break
done
logger -t cloud "$(basename $0): exit apply egress firewall rules for guest network"
return $result
}
aflag=0
rules=""
rules_list=""
ip=""
dev=""
shift
shift
while getopts 'a:' OPTION
do
case $OPTION in
a) aflag=1
rules="$OPTARG"
;;
?) usage
unlock_exit 2 $lock $locked
;;
esac
done
if [ "$aflag" != "1" ]
then
usage
unlock_exit 2 $lock $locked
fi
if [ -n "$rules" ]
then
rules_list=$(echo $rules | cut -d, -f1- --output-delimiter=" ")
fi
# rule format
# protocal:sport:eport:cidr
#-a tcp:80:80:0.0.0.0/0::tcp:220:220:0.0.0.0/0:,tcp:222:222:192.168.10.0/24-75.57.23.0/22-88.100.33.1/32
# if any entry is reverted , entry will be in the format reverted:0:0:0
# example : tcp:80:80:0.0.0.0/0:, tcp:220:220:0.0.0.0/0:,200.1.1.2:reverted:0:0:0
success=0
fw_egress_chain
for r in $rules_list
do
fw_entry_for_egress $r
success=$?
if [ $success -gt 0 ]
then
logger -t cloud "failure to apply fw egress rules "
break
else
logger -t cloud "successful in applying fw egress rules"
fi
done
if [ $success -gt 0 ]
then
logger -t cloud "restoring from backup for guest network"
fw_egress_backup_restore
else
logger -t cloud "deleting backup for guest network"
fi
fw_egress_remove_backup
unlock_exit $success $lock $locked

View File

@ -181,7 +181,7 @@ public class ApiRateLimitTest {
assertTrue("The first request should be allowed", isUnderLimit(key)); assertTrue("The first request should be allowed", isUnderLimit(key));
// Allow the token to expire // Allow the token to expire
Thread.sleep(1001); Thread.sleep(1020);
assertTrue("Another request after interval should be allowed as well", isUnderLimit(key)); assertTrue("Another request after interval should be allowed as well", isUnderLimit(key));
} }
@ -219,7 +219,8 @@ public class ApiRateLimitTest {
ApiLimitResponse response = _limitService.searchApiLimit(testAccount); ApiLimitResponse response = _limitService.searchApiLimit(testAccount);
assertEquals("apiIssued is incorrect", 5, response.getApiIssued()); assertEquals("apiIssued is incorrect", 5, response.getApiIssued());
assertEquals("apiAllowed is incorrect", 5, response.getApiAllowed()); assertEquals("apiAllowed is incorrect", 5, response.getApiAllowed());
assertTrue("expiredAfter is incorrect", response.getExpireAfter() < 1000); // using <= to account for inaccurate System.currentTimeMillis() clock in Windows environment
assertTrue("expiredAfter is incorrect", response.getExpireAfter() <= 1000);
} }

View File

@ -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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-hypervisor-baremetal</artifactId>
<name>Apache CloudStack Plugin - Hypervisor Baremetal</name>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,67 @@
#!/bin/sh
# the following is chkconfig init header
#
# cs-sgagent: cloudStack baremetal sercurity group agent
#
# chkconfig: 345 97 03
# description: This is a daemon instructed by CloudStack management server \
# to perform baremetal security group related operations\
#
# processname: cs-sgagent
# pidfile: /var/run/cssgagent.pid
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT 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_status() {
pidfile='/var/run/cssgagent.pid'
if [ ! -f $pidfile ]; then
echo "cloudstack baremetal security group agent is stopped"
exit 1
else
pid=`cat $pidfile`
ps -p $pid > /dev/null
if [ $? -eq 0 ]; then
echo "cloudstack baremetal security group agent is running, pid is $pid"
exit 0
else
echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok"
exit 1
fi
fi
}
if [ $# -eq 0 ]; then
echo "usage: $0
[start|stop|restart|status]"
exit 1
fi
if [ "$@" = "status" ]; then
check_status
else
python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" $@
fi
if [ $? -eq 0 ]; then
echo "$@ cloudstack baremetal security group agent .... SUCCESS"
exit 0
else
echo "$@ cloudstack baremetal security group agent .... FAILED"
exit 1
fi

View File

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013

View File

@ -0,0 +1,237 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
'''
Created on Jan 2, 2013
@author: frank
'''
import cherrypy
import sglib
import xmlobject
import types
import uuid
import os.path
import sys
import os
class SGRule(object):
def __init__(self):
self.protocol = None
self.start_port = None
self.end_port = None
self.allowed_ips = []
class IPSet(object):
IPSET_TYPE = 'hash:ip'
def __init__(self, setname, ips):
self.ips = ips
self.name = setname
def create(self):
tmpname = str(uuid.uuid4()).replace('-', '')[0:30]
sglib.ShellCmd('ipset -N %s %s' % (tmpname, self.IPSET_TYPE))()
try:
for ip in self.ips:
sglib.ShellCmd('ipset -A %s %s' % (tmpname, ip))()
try:
sglib.ShellCmd('ipset -N %s %s' % (self.name, self.IPSET_TYPE))()
cherrypy.log('created new ipset: %s' % self.name)
except Exception:
cherrypy.log('%s already exists, no need to create new' % self.name)
finally:
sglib.ShellCmd('ipset -W %s %s' % (tmpname, self.name))()
sglib.ShellCmd('ipset -F %s' % tmpname)()
sglib.ShellCmd('ipset -X %s' % tmpname)()
@staticmethod
def destroy_sets(sets_to_keep):
sets = sglib.ShellCmd('ipset list')()
for s in sets.split('\n'):
if 'Name:' in s:
set_name = s.split(':', 1)[1].strip()
if not set_name in sets_to_keep:
sglib.ShellCmd('ipset destroy %s' % set_name)()
cherrypy.log('destroyed unused ipset: %s' % set_name)
class SGAgent(object):
def __init__(self):
pass
def _self_list(self, obj):
if isinstance(obj, types.ListType):
return obj
else:
return [obj]
def set_rules(self, req):
body = req.body
doc = xmlobject.loads(body)
vm_name = doc.vmName.text_
vm_id = doc.vmId.text_
vm_ip = doc.vmIp.text_
vm_mac = doc.vmMac.text_
sig = doc.signature.text_
seq = doc.sequenceNumber.text_
def parse_rules(rules, lst):
for i in self._self_list(rules):
r = SGRule()
r.protocol = i.protocol.text_
r.start_port = i.startPort.text_
r.end_port = i.endPort.text_
if hasattr(i, 'ip'):
for ip in self._self_list(i.ip):
r.allowed_ips.append(ip.text_)
lst.append(r)
i_rules = []
if hasattr(doc, 'ingressRules'):
parse_rules(doc.ingressRules, i_rules)
e_rules = []
if hasattr(doc, 'egressRules'):
parse_rules(doc.egressRules, e_rules)
def create_chain(name):
try:
sglib.ShellCmd('iptables -F %s' % name)()
except Exception:
sglib.ShellCmd('iptables -N %s' % name)()
def apply_rules(rules, chainname, direction, action, current_set_names):
create_chain(chainname)
for r in i_rules:
allow_any = False
if '0.0.0.0/0' in r.allowed_ips:
allow_any = True
r.allowed_ips.remove('0.0.0.0/0')
if r.allowed_ips:
setname = '_'.join([chainname, r.protocol, r.start_port, r.end_port])
ipset = IPSet(setname, r.allowed_ips)
ipset.create()
current_set_names.append(setname)
if r.protocol == 'all':
cmd = ['iptables -I', chainname, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
elif r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
if allow_any and r.protocol != 'all':
if r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m', 'state', '--state', 'NEW', '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
current_sets = []
i_chain_name = vm_name + '-in'
apply_rules(i_rules, i_chain_name, 'src', 'ACCEPT', current_sets)
e_chain_name = vm_name + '-eg'
apply_rules(e_rules, e_chain_name, 'dst', 'RETURN', current_sets)
if e_rules:
sglib.ShellCmd('iptables -A %s -j RETURN' % e_chain_name)
else:
sglib.ShellCmd('iptables -A %s -j DROP' % e_chain_name)
sglib.ShellCmd('iptables -A %s -j DROP' % i_chain_name)
IPSet.destroy_sets(current_sets)
def echo(self, req):
cherrypy.log("echo: I am alive")
def index(self):
req = sglib.Request.from_cherrypy_request(cherrypy.request)
cmd_name = req.headers['command']
if not hasattr(self, cmd_name):
raise ValueError("SecurityGroupAgent doesn't have a method called '%s'" % cmd_name)
method = getattr(self, cmd_name)
return method(req)
index.exposed = True
@staticmethod
def start():
cherrypy.log.access_file = '/var/log/cs-securitygroup.log'
cherrypy.log.error_file = '/var/log/cs-securitygroup.log'
cherrypy.server.socket_host = '0.0.0.0'
cherrypy.server.socket_port = 9988
cherrypy.quickstart(SGAgent())
@staticmethod
def stop():
cherrypy.engine.exit()
PID_FILE = '/var/run/cssgagent.pid'
class SGAgentDaemon(sglib.Daemon):
def __init__(self):
super(SGAgentDaemon, self).__init__(PID_FILE)
self.is_stopped = False
self.agent = SGAgent()
sglib.Daemon.register_atexit_hook(self._do_stop)
def _do_stop(self):
if self.is_stopped:
return
self.is_stopped = True
self.agent.stop()
def run(self):
self.agent.start()
def stop(self):
self.agent.stop()
super(SGAgentDaemon, self).stop()
def main():
usage = 'usage: python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" start|stop|restart'
if len(sys.argv) != 2 or not sys.argv[1] in ['start', 'stop', 'restart']:
print usage
sys.exit(1)
cmd = sys.argv[1]
agentdaemon = SGAgentDaemon()
if cmd == 'start':
agentdaemon.start()
elif cmd == 'stop':
agentdaemon.stop()
else:
agentdaemon.restart()
sys.exit(0)

View File

@ -0,0 +1,226 @@
#!/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.
#
# Automatically generated by addcopyright.py at 01/29/2013
import sys, os, time, atexit
import traceback
import subprocess
from signal import SIGTERM
import cherrypy
import copy
class Request(object):
def __init__(self):
self.headers = None
self.body = None
self.method = None
self.query_string = None
@staticmethod
def from_cherrypy_request(creq):
req = Request()
req.headers = copy.copy(creq.headers)
req.body = creq.body.fp.read() if creq.body else None
req.method = copy.copy(creq.method)
req.query_string = copy.copy(creq.query_string) if creq.query_string else None
return req
class ShellError(Exception):
'''shell error'''
class ShellCmd(object):
'''
classdocs
'''
def __init__(self, cmd, workdir=None, pipe=True):
'''
Constructor
'''
self.cmd = cmd
if pipe:
self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir)
else:
self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir)
self.stdout = None
self.stderr = None
self.return_code = None
def __call__(self, is_exception=True):
(self.stdout, self.stderr) = self.process.communicate()
if is_exception and self.process.returncode != 0:
err = []
err.append('failed to execute shell command: %s' % self.cmd)
err.append('return code: %s' % self.process.returncode)
err.append('stdout: %s' % self.stdout)
err.append('stderr: %s' % self.stderr)
raise ShellError('\n'.join(err))
self.return_code = self.process.returncode
return self.stdout
class Daemon(object):
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
atexit_hooks = []
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
@staticmethod
def register_atexit_hook(hook):
Daemon.atexit_hooks.append(hook)
@staticmethod
def _atexit():
for hook in Daemon.atexit_hooks:
try:
hook()
except Exception:
content = traceback.format_exc()
err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content)
#logger.error(err)
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
Daemon.register_atexit_hook(self.delpid)
atexit.register(Daemon._atexit)
pid = str(os.getpid())
file(self.pidfile,'w').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
pscmd = ShellCmd('ps -p %s > /dev/null' % pid)
pscmd(is_exception=False)
if pscmd.return_code == 0:
message = "Daemon already running, pid is %s\n"
sys.stderr.write(message % pid)
sys.exit(0)
# Start the daemon
self.daemonize()
try:
self.run()
except Exception:
content = traceback.format_exc()
#logger.error(content)
sys.exit(1)
def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def run(self):
"""
You should override this method when you subclass Daemon. It will be called after the process has been
daemonized by start() or restart().
"""

View File

@ -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.
#
# Automatically generated by addcopyright.py at 01/29/2013
'''
Created on Dec 25, 2012
@author: Frank
'''
import xml.etree.ElementTree as etree
import re
import types
class XmlObject(object):
def __init__(self, tag):
self.__tag_name__ = tag
def put_attr(self, name, val):
val = val.strip().strip('\t')
setattr(self, name + '_', val)
def put_text(self, val):
val = val.strip().strip('\n').strip('\t')
if val == "":
setattr(self, 'text_', None)
else:
setattr(self, 'text_', val)
def put_node(self, name, val):
if not hasattr(self, name):
setattr(self, name, val)
return
nodes = getattr(self, name)
if not isinstance(nodes, types.ListType):
nodes = []
old = getattr(self, name)
nodes.append(old)
nodes.append(val)
setattr(self, name, nodes)
else:
nodes.append(val)
setattr(self, name, nodes)
def get(self, name, default=None):
if hasattr(self, name):
val = getattr(self, name)
if name.endswith('_'):
return val
else:
return val.text_
else:
return default
def __getattr__(self, name):
if name.endswith('__'):
n = name[:-1]
if hasattr(self, n):
return getattr(self, n)
else:
return None
else:
e = AttributeError('%s has no attribute %s. missing attribute %s in element <%s>' % (self.__class__.__name__, name, name, self.__tag_name__))
setattr(e, 'missing_attrib', name)
setattr(e, 'tag_name', self.__tag_name__)
raise e
def _loads(node):
xo = XmlObject(node.tag)
for key in node.attrib.keys():
xo.put_attr(key, node.attrib.get(key))
if node.text:
xo.put_text(node.text)
for n in list(node):
sub_xo = _loads(n)
xo.put_node(n.tag, sub_xo)
return xo
def loads(xmlstr):
xmlstr = re.sub(r'xmlns=".*"', '', xmlstr)
root = etree.fromstring(xmlstr)
return _loads(root)

View File

@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
from setuptools import setup, find_packages
import sys, os
version = '1.0'
setup(name='security_group_agent',
version=version,
description="security group agent for CloudStack Baremetal",
long_description="""\
security group agent for CloudStack Baremetal""",
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords='security group cloudstack',
author='Frank Zhang',
author_email='frank.zhang@citrix.com',
url='http://incubator.apache.org/cloudstack/',
license='Apache License 2',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
include_package_data=True,
zip_safe=True,
install_requires=[
'CherryPy',
],
entry_points="""
# -*- Entry points: -*-
""",
)

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
public interface BaremetalCmdbDao extends GenericDao<BaremetalCmdbVO, Long> {
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import javax.ejb.Local;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
@Local(value = {BaremetalCmdbDao.class})
@DB(txn = false)
public class BaremetalCmdbDaoImpl extends GenericDaoBase<BaremetalCmdbVO, Long> implements BaremetalCmdbDao {
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_cmdb")
public class BaremetalCmdbVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name="zone_id")
private long zoneId;
@Column(name="url")
private String url;
@Column(name="password")
private String password;
@Column(name="username")
private String username;
public BaremetalCmdbVO() {
uuid = UUID.randomUUID().toString();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getZoneId() {
return zoneId;
}
public void setZoneId(long zoneId) {
this.zoneId = zoneId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
public interface BaremetalDhcpDao extends GenericDao<BaremetalDhcpVO, Long> {
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria2;
@Local(value=BaremetalDhcpDao.class)
@DB(txn=false)
public class BaremetalDhcpDaoImpl extends GenericDaoBase<BaremetalDhcpVO, Long> implements BaremetalDhcpDao {
public BaremetalDhcpDaoImpl() {
}
}

View File

@ -0,0 +1,118 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_dhcp_devices")
public class BaremetalDhcpVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name = "host_id")
private long hostId;
@Column(name = "pod_id")
private long podId;
@Column(name = "physical_network_id")
private long physicalNetworkId;
@Column(name = "nsp_id")
private long networkServiceProviderId ;
@Column(name = "device_type")
private String deviceType;
public BaremetalDhcpVO() {
super();
this.uuid = UUID.randomUUID().toString();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getHostId() {
return hostId;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public long getNetworkServiceProviderId() {
return networkServiceProviderId;
}
public void setNetworkServiceProviderId(long networkServiceProviderId) {
this.networkServiceProviderId = networkServiceProviderId;
}
public long getPodId() {
return podId;
}
public void setPodId(long podId) {
this.podId = podId;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.GenericDaoBase;
public interface BaremetalPxeDao extends GenericDao<BaremetalPxeVO, Long> {
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria2;
@Local(value = {BaremetalPxeDao.class})
@DB(txn = false)
public class BaremetalPxeDaoImpl extends GenericDaoBase<BaremetalPxeVO, Long> implements BaremetalPxeDao {
}

View File

@ -0,0 +1,115 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_pxe_devices")
public class BaremetalPxeVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name = "host_id")
private long hostId;
@Column(name = "pod_id")
private long podId;
@Column(name = "physical_network_id")
private long physicalNetworkId;
@Column(name = "nsp_id")
private long networkServiceProviderId ;
@Column(name = "device_type")
private String deviceType;
public long getId() {
return id;
}
public BaremetalPxeVO() {
uuid = UUID.randomUUID().toString();
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getHostId() {
return hostId;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public long getNetworkServiceProviderId() {
return networkServiceProviderId;
}
public void setNetworkServiceProviderId(long networkServiceProviderId) {
this.networkServiceProviderId = networkServiceProviderId;
}
public long getPodId() {
return podId;
}
public void setPodId(long podId) {
this.podId = podId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.admin.host.AddHostCmd;
public class AddBaremetalHostCmd extends AddHostCmd {
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="ip address intentionally allocated to this host after provisioning")
private String vmIpAddress;
public AddBaremetalHostCmd() {
this.getFullUrlParams().put(ApiConstants.BAREMETAL_DISCOVER_NAME, BareMetalDiscoverer.class.getName());
}
public String getVmIpAddress() {
return vmIpAddress;
}
public void setVmIpAddress(String vmIpAddress) {
this.vmIpAddress = vmIpAddress;
}
}

View File

@ -0,0 +1,280 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.net.InetAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.baremetal.networkservice.BareMetalResourceBase;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.DiscoveryException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value=Discoverer.class)
public class BareMetalDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
protected static final Logger s_logger = Logger.getLogger(BareMetalDiscoverer.class);
@Inject protected ClusterDao _clusterDao;
@Inject protected HostDao _hostDao;
@Inject protected DataCenterDao _dcDao;
@Inject protected VMInstanceDao _vmDao = null;
@Inject protected ResourceManager _resourceMgr;
@Inject protected ConfigurationDao _configDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return super.configure(name, params);
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return super.stop();
}
@Override
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags)
throws DiscoveryException {
String discoverName = _params.get(ApiConstants.BAREMETAL_DISCOVER_NAME);
if (!this.getClass().getName().equals(discoverName)) {
return null;
}
Map<BareMetalResourceBase, Map<String, String>> resources = new HashMap<BareMetalResourceBase, Map<String, String>>();
Map<String, String> details = new HashMap<String, String>();
if (!url.getScheme().equals("http")) {
String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
s_logger.debug(msg);
return null;
}
if (clusterId == null) {
String msg = "must specify cluster Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
if (podId == null) {
String msg = "must specify pod Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
ClusterVO cluster = _clusterDao.findById(clusterId);
if (cluster == null || (cluster.getHypervisorType() != HypervisorType.BareMetal)) {
if (s_logger.isInfoEnabled())
s_logger.info("invalid cluster id or cluster is not for Bare Metal hosts");
return null;
}
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new RuntimeException("Cannot find zone " + dcId);
}
try {
String hostname = url.getHost();
InetAddress ia = InetAddress.getByName(hostname);
String ipmiIp = ia.getHostAddress();
String guid = UUID.nameUUIDFromBytes(ipmiIp.getBytes()).toString();
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new CloudRuntimeException("Unable to find key ipmi script "
+ injectScript);
}
final Script2 command = new Script2(scriptPath, s_logger);
command.add("ping");
command.add("hostname="+ipmiIp);
command.add("usrname="+username);
command.add("password="+password, ParamType.PASSWORD);
final String result = command.execute();
if (result != null) {
s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result));
return null;
}
ClusterVO clu = _clusterDao.findById(clusterId);
if (clu.getGuid() == null) {
clu.setGuid(UUID.randomUUID().toString());
_clusterDao.update(clusterId, clu);
}
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(_params);
params.put("zone", Long.toString(dcId));
params.put("pod", Long.toString(podId));
params.put("cluster", Long.toString(clusterId));
params.put("guid", guid);
params.put(ApiConstants.PRIVATE_IP, ipmiIp);
params.put(ApiConstants.USERNAME, username);
params.put(ApiConstants.PASSWORD, password);
String resourceClassName = _configDao.getValue(Config.ExternalBaremetalResourceClassName.key());
BareMetalResourceBase resource = null;
if (resourceClassName != null) {
Class<?> clazz = Class.forName(resourceClassName);
resource = (BareMetalResourceBase) clazz.newInstance();
String externalUrl = _configDao.getValue(Config.ExternalBaremetalSystemUrl.key());
if (externalUrl == null) {
throw new IllegalArgumentException(String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null"));
}
details.put(BaremetalManager.ExternalBaremetalSystemUrl, externalUrl);
} else {
resource = new BareMetalResourceBase();
}
resource.configure("Bare Metal Agent", params);
String memCapacity = (String)params.get(ApiConstants.MEMORY);
String cpuCapacity = (String)params.get(ApiConstants.CPU_SPEED);
String cpuNum = (String)params.get(ApiConstants.CPU_NUMBER);
String mac = (String)params.get(ApiConstants.HOST_MAC);
if (hostTags != null && hostTags.size() != 0) {
details.put("hostTag", hostTags.get(0));
}
details.put(ApiConstants.MEMORY, memCapacity);
details.put(ApiConstants.CPU_SPEED, cpuCapacity);
details.put(ApiConstants.CPU_NUMBER, cpuNum);
details.put(ApiConstants.HOST_MAC, mac);
details.put(ApiConstants.USERNAME, username);
details.put(ApiConstants.PASSWORD, password);
details.put(ApiConstants.PRIVATE_IP, ipmiIp);
String vmIp = (String)params.get(ApiConstants.IP_ADDRESS);
if (vmIp != null) {
details.put(ApiConstants.IP_ADDRESS, vmIp);
}
String isEchoScAgent = _configDao.getValue(Config.EnableBaremetalSecurityGroupAgentEcho.key());
details.put(BaremetalManager.EchoSecurityGroupAgent, isEchoScAgent);
resources.put(resource, details);
resource.start();
zone.setGatewayProvider(Network.Provider.ExternalGateWay.getName());
zone.setDnsProvider(Network.Provider.ExternalDhcpServer.getName());
zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName());
_dcDao.update(zone.getId(), zone);
s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," +
"cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity));
return resources;
} catch (Exception e) {
s_logger.warn("Can not set up bare metal agent", e);
}
return null;
}
@Override
public void postDiscovery(List<HostVO> hosts, long msId)
throws DiscoveryException {
}
@Override
public boolean matchHypervisor(String hypervisor) {
return hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.BareMetal.toString());
}
@Override
public HypervisorType getHypervisorType() {
return Hypervisor.HypervisorType.BareMetal;
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
StartupCommand firstCmd = startup[0];
if (!(firstCmd instanceof StartupRoutingCommand)) {
return null;
}
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
if (ssCmd.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.BareMetal, details, hostTags);
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
List<VMInstanceVO> deadVms = _vmDao.listByLastHostId(host.getId());
for (VMInstanceVO vm : deadVms) {
if (vm.getState() == State.Running || vm.getHostId() != null) {
throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + host.getId());
}
_vmDao.remove(vm.getId());
}
return new DeleteHostAnswer(true);
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruBase;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.utils.component.Inject;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value=HypervisorGuru.class)
public class BareMetalGuru extends HypervisorGuruBase implements HypervisorGuru {
private static final Logger s_logger = Logger.getLogger(BareMetalGuru.class);
@Inject GuestOSDao _guestOsDao;
@Inject HostDao _hostDao;
@Inject VMInstanceDao _vmDao;
protected BareMetalGuru() {
super();
}
@Override
public HypervisorType getHypervisorType() {
return HypervisorType.BareMetal;
}
@Override
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
VirtualMachineTO to = toVirtualMachineTO(vm);
VMInstanceVO vo = _vmDao.findById(vm.getId());
if (vo.getLastHostId() == null) {
to.setBootArgs(BaremetalManager.DO_PXE);
}
Map<String, String> details = new HashMap<String, String>();
details.put("template", vm.getTemplate().getUrl());
to.setDetails(details);
// Determine the VM's OS description
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
to.setOs(guestOS.getDisplayName());
return to;
}
@Override
public boolean trackVmHostChange() {
return false;
}
}

View File

@ -0,0 +1,217 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.log4j.Logger;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.template.TemplateAdapter;
import com.cloud.template.TemplateAdapterBase;
import com.cloud.template.TemplateProfile;
import com.cloud.user.Account;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value=TemplateAdapter.class)
public class BareMetalTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
private final static Logger s_logger = Logger.getLogger(BareMetalTemplateAdapter.class);
@Inject HostDao _hostDao;
@Inject ResourceManager _resourceMgr;
@Override
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException {
TemplateProfile profile = super.prepare(cmd);
if (profile.getZoneId() == null || profile.getZoneId() == -1) {
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
for (DataCenterVO dc : dcs) {
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId());
if (pxeServers.size() == 0) {
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + dc.getName());
}
}
} else {
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, profile.getZoneId());
if (pxeServers.size() == 0) {
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + profile.getZoneId());
}
}
return profile;
}
@Override
public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException {
throw new CloudRuntimeException("Baremetal doesn't support ISO template");
}
private void templateCreateUsage(VMTemplateVO template, HostVO host) {
if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(),
template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L);
_usageEventDao.persist(usageEvent);
}
}
@Override
public VMTemplateVO create(TemplateProfile profile) {
VMTemplateVO template = persistTemplate(profile);
Long zoneId = profile.getZoneId();
/* There is no secondary storage vm for baremetal, we use pxe server id.
* Tempalte is not bound to pxeserver right now, and we assume the pxeserver
* cannot be removed once it was added. so we use host id of first found pxe
* server as reference in template_host_ref.
* This maybe a FIXME in future.
*/
VMTemplateHostVO vmTemplateHost = null;
if (zoneId == null || zoneId == -1) {
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
for (DataCenterVO dc : dcs) {
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId()).get(0);
vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId());
if (vmTemplateHost == null) {
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
Status.DOWNLOADED, null, null, null, null, template.getUrl());
_tmpltHostDao.persist(vmTemplateHost);
templateCreateUsage(template, pxe);
}
}
} else {
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId).get(0);
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
Status.DOWNLOADED, null, null, null, null, template.getUrl());
_tmpltHostDao.persist(vmTemplateHost);
templateCreateUsage(template, pxe);
}
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
return template;
}
public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???");
}
@Override @DB
public boolean delete(TemplateProfile profile) {
VMTemplateVO template = profile.getTemplate();
Long templateId = template.getId();
boolean success = true;
String zoneName;
boolean isAllZone;
if (!template.isCrossZones() && profile.getZoneId() != null) {
isAllZone = false;
zoneName = profile.getZoneId().toString();
} else {
zoneName = "all zones";
isAllZone = true;
}
s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
String eventType = EventTypes.EVENT_TEMPLATE_DELETE;
List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByTemplateId(templateId);
for (VMTemplateHostVO vo : templateHostVOs) {
VMTemplateHostVO lock = null;
try {
HostVO pxeServer = _hostDao.findById(vo.getHostId());
if (!isAllZone && pxeServer.getDataCenterId() != profile.getZoneId()) {
continue;
}
lock = _tmpltHostDao.acquireInLockTable(vo.getId());
if (lock == null) {
s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + vo.getId());
success = false;
break;
}
vo.setDestroyed(true);
_tmpltHostDao.update(vo.getId(), vo);
VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(pxeServer.getDataCenterId(), templateId);
if (templateZone != null) {
_tmpltZoneDao.remove(templateZone.getId());
}
UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null);
_usageEventDao.persist(usageEvent);
} finally {
if (lock != null) {
_tmpltHostDao.releaseFromLockTable(lock.getId());
}
}
}
s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
// If there are no more non-destroyed template host entries for this template, delete it
if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) {
long accountId = template.getAccountId();
VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);
try {
if (lock == null) {
s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
success = false;
} else if (_tmpltDao.remove(templateId)) {
// Decrement the number of templates
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
}
} finally {
if (lock != null) {
_tmpltDao.releaseFromLockTable(lock.getId());
}
}
s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed.");
}
return success;
}
}

View File

@ -0,0 +1,28 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import com.cloud.network.Network.Provider;
import com.cloud.utils.component.Manager;
public interface BaremetalManager extends Manager {
public static final String EchoSecurityGroupAgent = "EchoSecurityGroupAgent";
public static final String ExternalBaremetalSystemUrl = "ExternalBaremetalSystemUrl";
public static final String DO_PXE = "doPxe";
}

View File

@ -0,0 +1,112 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.manager.Commands;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.component.Inject;
import com.cloud.utils.fsm.StateListener;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineGuru;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = {BaremetalManager.class})
public class BaremetalManagerImpl implements BaremetalManager, StateListener<State, VirtualMachine.Event, VirtualMachine> {
private static final Logger s_logger = Logger.getLogger(BaremetalManagerImpl.class);
@Inject
protected HostDao _hostDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
VirtualMachine.State.getStateMachine().registerListener(this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return "Baremetal Manager";
}
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
return false;
}
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
return true;
}
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
return true;
}
HostVO host = _hostDao.findById(vo.getHostId());
if (host == null) {
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
return true;
}
_hostDao.loadDetails(host);
if (newState == State.Starting) {
host.setDetail("vmName", vo.getInstanceName());
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
} else {
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
host.getDetails().remove("vmName");
}
}
_hostDao.saveDetails(host);
return true;
}
}

View File

@ -0,0 +1,149 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
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.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalDhcpVO;
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.user.UserContext;
public class AddBaremetalDhcpCmd extends BaseAsyncCmd {
private static final String s_name = "addexternaldhcpresponse";
public static final Logger s_logger = Logger.getLogger(AddBaremetalDhcpCmd.class);
@PlugService BaremetalDhcpManager mgr;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, required = true, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.DHCP_SERVER_TYPE, type=CommandType.STRING, required = true, description="Type of dhcp device")
private String dhcpType;
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external dhcp appliance.")
private String url;
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
private String username;
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
private String password;
@Override
public String getEventType() {
return EventTypes.EVENT_BAREMETAL_DHCP_SERVER_ADD;
}
@Override
public String getEventDescription() {
return "Adding an external DHCP server";
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
BaremetalDhcpVO vo = mgr.addDchpServer(this);
BaremetalDhcpResponse response = mgr.generateApiResponse(vo);
response.setObjectName(s_name);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.warn("Unable to add external dhcp server with url: " + getUrl(), e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return UserContext.current().getCaller().getId();
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getDhcpType() {
return dhcpType;
}
public void setDhcpType(String dhcpType) {
this.dhcpType = dhcpType;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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 Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(Long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
public class AddBaremetalKickStartPxeCmd extends AddBaremetalPxeCmd {
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
private String tftpDir;
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,144 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
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.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalPxeVO;
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.user.UserContext;
public class AddBaremetalPxeCmd extends BaseAsyncCmd {
private static final String s_name = "addexternalpxeresponse";
public static final Logger s_logger = Logger.getLogger(AddBaremetalPxeCmd.class);
@PlugService BaremetalPxeManager pxeMgr;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external pxe device")
private String url;
@Parameter(name=ApiConstants.PXE_SERVER_TYPE, type=CommandType.STRING, required = true, description="type of pxe device")
private String deviceType;
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
private String username;
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
private String password;
@Override
public String getEventType() {
return EventTypes.EVENT_BAREMETAL_PXE_SERVER_ADD;
}
@Override
public String getEventDescription() {
return "Adding an external pxe server";
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
BaremetalPxeVO vo = pxeMgr.addPxeServer(this);
} catch (Exception e) {
s_logger.warn("Unable to add external pxe server with url: " + getUrl(), e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return UserContext.current().getCaller().getId();
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(Long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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 getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,80 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
public class AddBaremetalPxePingServerCmd extends AddBaremetalPxeCmd {
@Parameter(name=ApiConstants.PING_STORAGE_SERVER_IP, type=CommandType.STRING, required = true, description="PING storage server ip")
private String pingStorageServerIp;
@Parameter(name=ApiConstants.PING_DIR, type=CommandType.STRING, required = true, description="Root directory on PING storage server")
private String pingDir;
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
private String tftpDir;
@Parameter(name=ApiConstants.PING_CIFS_USERNAME, type=CommandType.STRING, description="Username of PING storage server")
private String pingStorageServerUserName;
@Parameter(name=ApiConstants.PING_CIFS_PASSWORD, type=CommandType.STRING, description="Password of PING storage server")
private String pingStorageServerPassword;
public String getPingStorageServerIp() {
return pingStorageServerIp;
}
public void setPingStorageServerIp(String pingStorageServerIp) {
this.pingStorageServerIp = pingStorageServerIp;
}
public String getPingDir() {
return pingDir;
}
public void setPingDir(String pingDir) {
this.pingDir = pingDir;
}
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
public String getPingStorageServerUserName() {
return pingStorageServerUserName;
}
public void setPingStorageServerUserName(String pingStorageServerUserName) {
this.pingStorageServerUserName = pingStorageServerUserName;
}
public String getPingStorageServerPassword() {
return pingStorageServerPassword;
}
public void setPingStorageServerPassword(String pingStorageServerPassword) {
this.pingStorageServerPassword = pingStorageServerPassword;
}
}

View File

@ -0,0 +1,300 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
import com.cloud.baremetal.database.BaremetalPxeDao;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=BaremetalPxeService.class)
public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
private static final Logger s_logger = Logger.getLogger(BareMetalPingServiceImpl.class);
@Inject ResourceManager _resourceMgr;
@Inject PhysicalNetworkDao _physicalNetworkDao;
@Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject HostDetailsDao _hostDetailsDao;
@Inject BaremetalPxeDao _pxeDao;
@Override
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, dest.getPod().getId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No PING PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
}
long pxeServerId = pxeVo.getHostId();
String mac = pxeNic.getMacAddress();
String ip = pxeNic.getIp4Address();
String gateway = pxeNic.getGateway();
String mask = pxeNic.getNetmask();
String dns = pxeNic.getDns1();
if (dns == null) {
dns = pxeNic.getDns2();
}
try {
String tpl = profile.getTemplate().getUrl();
assert tpl != null : "How can a null template get here!!!";
PreparePxeServerCommand cmd = new PreparePxeServerCommand(ip, mac, mask, gateway, dns, tpl,
profile.getVirtualMachine().getInstanceName(), dest.getHost().getName());
PreparePxeServerAnswer ans = (PreparePxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
if (!ans.getResult()) {
s_logger.warn("Unable tot program PXE server: " + pxeVo.getId() + " because " + ans.getDetails());
return false;
}
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
Answer anw = _agentMgr.send(dest.getHost().getId(), bootCmd);
if (!anw.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + anw.getDetails());
}
return anw.getResult();
} catch (Exception e) {
s_logger.warn("Cannot prepare PXE server", e);
return false;
}
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
if (nics.size() != 1) {
throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId());
}
/* use last host id when VM stopped */
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
HostVO host = _hostDao.findById(hostId);
DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
NicVO nic = nics.get(0);
String mask = nic.getNetmask();
String mac = nic.getMacAddress();
String ip = nic.getIp4Address();
String gateway = nic.getGateway();
String dns = dc.getDns1();
if (dns == null) {
dns = dc.getDns2();
}
try {
prepareCreateTemplateCommand cmd = new prepareCreateTemplateCommand(ip, mac, mask, gateway, dns, templateUrl);
Answer ans = _agentMgr.send(pxeServerId, cmd);
return ans.getResult();
} catch (Exception e) {
s_logger.debug("Prepare for creating baremetal template failed", e);
return false;
}
}
@Override
@DB
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
AddBaremetalPxePingServerCmd pcmd = (AddBaremetalPxePingServerCmd)cmd;
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
HostPodVO pod = _podDao.findById(cmd.getPodId());
if (pod == null) {
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
}
List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalPxe, null, cmd.getPodId(), zoneId);
if (pxes.size() != 0) {
throw new IllegalArgumentException("Already had a PXE server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
}
String storageServerIp = pcmd.getPingStorageServerIp();
if (storageServerIp == null) {
throw new IllegalArgumentException("No IP for storage server specified");
}
String pingDir = pcmd.getPingDir();
if (pingDir == null) {
throw new IllegalArgumentException("No direcotry for storage server specified");
}
String tftpDir = pcmd.getTftpDir();
if (tftpDir == null) {
throw new IllegalArgumentException("No TFTP directory specified");
}
String cifsUsername = pcmd.getPingStorageServerUserName();
if (cifsUsername == null || cifsUsername.equalsIgnoreCase("")) {
cifsUsername = "xxx";
}
String cifsPassword = pcmd.getPingStorageServerPassword();
if (cifsPassword == null || cifsPassword.equalsIgnoreCase("")) {
cifsPassword = "xxx";
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getPxeServerGuid(Long.toString(zoneId) + "-" + pod.getId(), BaremetalPxeType.PING.toString(), ipAddress);
ServerResource resource = null;
Map params = new HashMap<String, String>();
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
params.put(BaremetalPxeService.PXE_PARAM_POD, String.valueOf(pod.getId()));
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP, storageServerIp);
params.put(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR, pingDir);
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME, cifsUsername);
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD, cifsPassword);
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
resource = new BaremetalPingPxeResource();
try {
resource.configure("PING PXE resource", params);
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
if (pxeServer == null) {
throw new CloudRuntimeException("Cannot add PXE server as a host");
}
BaremetalPxeVO vo = new BaremetalPxeVO();
Transaction txn = Transaction.currentTxn();
vo.setHostId(pxeServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPodId(pod.getId());
vo.setPhysicalNetworkId(pcmd.getPhysicalNetworkId());
vo.setDeviceType(BaremetalPxeType.PING.toString());
txn.start();
_pxeDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
BaremetalPxePingResponse response = new BaremetalPxePingResponse();
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setPodId(String.valueOf(vo.getPodId()));
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
response.setPingStorageServerIp(details.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP));
response.setPingDir(details.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR));
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
return response;
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalPxeVO> vos = sc.list();
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
for (BaremetalPxeVO vo : vos) {
responses.add(getApiResponse(vo));
}
return responses;
}
}

View File

@ -0,0 +1,68 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.Map;
import javax.naming.ConfigurationException;
import com.cloud.agent.AgentManager;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.host.dao.HostDao;
import com.cloud.utils.component.Inject;
import com.cloud.vm.dao.NicDao;
public abstract class BareMetalPxeServiceBase implements BaremetalPxeService {
protected String _name;
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject HostPodDao _podDao;
@Inject NicDao _nicDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
protected String getPxeServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
}

View File

@ -0,0 +1,618 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecurityGroupRulesCmd;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.baremetal.manager.BaremetalManager;
import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.ServerResource;
import com.cloud.server.ManagementServer;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
@Local(value = ServerResource.class)
public class BareMetalResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BareMetalResourceBase.class);
protected HashMap<String, State> _vms = new HashMap<String, State>(2);
protected String _name;
protected String _uuid;
protected String _zone;
protected String _pod;
protected Long hostId;
protected String _cluster;
protected long _memCapacity;
protected long _cpuCapacity;
protected long _cpuNum;
protected String _mac;
protected String _username;
protected String _password;
protected String _ip;
protected boolean _isEchoScAgent;
protected IAgentControl _agentControl;
protected Script2 _pingCommand;
protected Script2 _setPxeBootCommand;
protected Script2 _setDiskBootCommand;
protected Script2 _rebootCommand;
protected Script2 _getStatusCommand;
protected Script2 _powerOnCommand;
protected Script2 _powerOffCommand;
protected Script2 _forcePowerOffCommand;
protected Script2 _bootOrRebootCommand;
protected String _vmName;
protected VMInstanceDao vmDao;
private void changeVmState(String vmName, VirtualMachine.State state) {
synchronized (_vms) {
_vms.put(vmName, state);
}
}
private State removeVmState(String vmName) {
synchronized (_vms) {
return _vms.remove(vmName);
}
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_uuid = (String) params.get("guid");
try {
_memCapacity = Long.parseLong((String) params.get(ApiConstants.MEMORY)) * 1024L * 1024L;
_cpuCapacity = Long.parseLong((String) params.get(ApiConstants.CPU_SPEED));
_cpuNum = Long.parseLong((String) params.get(ApiConstants.CPU_NUMBER));
} catch (NumberFormatException e) {
throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity "
+ "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", (String) params.get(ApiConstants.CPU_NUMBER),
(String) params.get(ApiConstants.MEMORY), (String) params.get(ApiConstants.CPU_SPEED)));
}
_zone = (String) params.get("zone");
_pod = (String) params.get("pod");
_cluster = (String) params.get("cluster");
hostId = (Long) params.get("hostId");
_ip = (String) params.get(ApiConstants.PRIVATE_IP);
_mac = (String) params.get(ApiConstants.HOST_MAC);
_username = (String) params.get(ApiConstants.USERNAME);
_password = (String) params.get(ApiConstants.PASSWORD);
_vmName = (String) params.get("vmName");
String echoScAgent = (String) params.get(BaremetalManager.EchoSecurityGroupAgent);
if (_pod == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_cluster == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_ip == null) {
throw new ConfigurationException("Unable to get the host address");
}
if (_mac.equalsIgnoreCase("unknown")) {
throw new ConfigurationException("Unable to get the host mac address");
}
if (_mac.split(":").length != 6) {
throw new ConfigurationException("Wrong MAC format(" + _mac
+ "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive");
}
if (_uuid == null) {
throw new ConfigurationException("Unable to get the uuid");
}
if (echoScAgent != null) {
_isEchoScAgent = Boolean.valueOf(echoScAgent);
}
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new ConfigurationException("Cannot find ping script " + scriptPath);
}
_pingCommand = new Script2(scriptPath, s_logger);
_pingCommand.add("ping");
_pingCommand.add("hostname=" + _ip);
_pingCommand.add("usrname=" + _username);
_pingCommand.add("password=" + _password, ParamType.PASSWORD);
_setPxeBootCommand = new Script2(scriptPath, s_logger);
_setPxeBootCommand.add("boot_dev");
_setPxeBootCommand.add("hostname=" + _ip);
_setPxeBootCommand.add("usrname=" + _username);
_setPxeBootCommand.add("password=" + _password, ParamType.PASSWORD);
_setPxeBootCommand.add("dev=pxe");
_setDiskBootCommand = new Script2(scriptPath, s_logger);
_setDiskBootCommand.add("boot_dev");
_setDiskBootCommand.add("hostname=" + _ip);
_setDiskBootCommand.add("usrname=" + _username);
_setDiskBootCommand.add("password=" + _password, ParamType.PASSWORD);
_setDiskBootCommand.add("dev=disk");
_rebootCommand = new Script2(scriptPath, s_logger);
_rebootCommand.add("reboot");
_rebootCommand.add("hostname=" + _ip);
_rebootCommand.add("usrname=" + _username);
_rebootCommand.add("password=" + _password, ParamType.PASSWORD);
_getStatusCommand = new Script2(scriptPath, s_logger);
_getStatusCommand.add("ping");
_getStatusCommand.add("hostname=" + _ip);
_getStatusCommand.add("usrname=" + _username);
_getStatusCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOnCommand = new Script2(scriptPath, s_logger);
_powerOnCommand.add("power");
_powerOnCommand.add("hostname=" + _ip);
_powerOnCommand.add("usrname=" + _username);
_powerOnCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOnCommand.add("action=on");
_powerOffCommand = new Script2(scriptPath, s_logger);
_powerOffCommand.add("power");
_powerOffCommand.add("hostname=" + _ip);
_powerOffCommand.add("usrname=" + _username);
_powerOffCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOffCommand.add("action=soft");
_forcePowerOffCommand = new Script2(scriptPath, s_logger);
_forcePowerOffCommand.add("power");
_forcePowerOffCommand.add("hostname=" + _ip);
_forcePowerOffCommand.add("usrname=" + _username);
_forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD);
_forcePowerOffCommand.add("action=off");
_bootOrRebootCommand = new Script2(scriptPath, s_logger);
_bootOrRebootCommand.add("boot_or_reboot");
_bootOrRebootCommand.add("hostname=" + _ip);
_bootOrRebootCommand.add("usrname=" + _username);
_bootOrRebootCommand.add("password=" + _password, ParamType.PASSWORD);
return true;
}
protected boolean doScript(Script cmd) {
return doScript(cmd, null);
}
protected boolean doScript(Script cmd, OutputInterpreter interpreter) {
int retry = 5;
String res = null;
while (retry-- > 0) {
if (interpreter == null) {
res = cmd.execute();
} else {
res = cmd.execute(interpreter);
}
if (res != null && res.startsWith("Error: Unable to establish LAN")) {
s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times");
continue;
} else if (res == null) {
return true;
} else {
break;
}
}
s_logger.warn("IPMI Scirpt failed due to " + res + "(" + cmd.toString() + ")");
return false;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public Type getType() {
return com.cloud.host.Host.Type.Routing;
}
protected State getVmState() {
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
return null;
}
if (isPowerOn(interpreter.getLines())) {
return State.Running;
} else {
return State.Stopped;
}
}
protected Map<String, State> fullSync() {
Map<String, State> states = new HashMap<String, State>();
if (hostId != null) {
ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
vmDao = locator.getDao(VMInstanceDao.class);
final List<? extends VMInstanceVO> vms = vmDao.listByHostId(hostId);
for (VMInstanceVO vm : vms) {
states.put(vm.getInstanceName(), vm.getState());
}
}
/*
* Map<String, State> changes = new HashMap<String, State>();
*
* if (_vmName != null) { State state = getVmState(); if (state != null)
* { changes.put(_vmName, state); } }
*/
return states;
}
@Override
public StartupCommand[] initialize() {
StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap<String, String>(), null);
cmd.setDataCenter(_zone);
cmd.setPod(_pod);
cmd.setCluster(_cluster);
cmd.setGuid(_uuid);
cmd.setName(_ip);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress(_ip);
cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion());
cmd.setCpus((int) _cpuNum);
cmd.setSpeed(_cpuCapacity);
cmd.setMemory(_memCapacity);
cmd.setPrivateMacAddress(_mac);
cmd.setPublicMacAddress(_mac);
cmd.setStateChanges(fullSync());
return new StartupCommand[] { cmd };
}
private boolean ipmiPing() {
return doScript(_pingCommand);
}
@Override
public PingCommand getCurrentStatus(long id) {
try {
if (!ipmiPing()) {
Thread.sleep(1000);
if (!ipmiPing()) {
s_logger.warn("Cannot ping ipmi nic " + _ip);
return null;
}
}
} catch (Exception e) {
s_logger.debug("Cannot ping ipmi nic " + _ip, e);
return null;
}
return new PingRoutingCommand(getType(), id, deltaSync());
}
protected Answer execute(IpmISetBootDevCommand cmd) {
Script bootCmd = null;
if (cmd.getBootDev() == BootDev.disk) {
bootCmd = _setDiskBootCommand;
} else if (cmd.getBootDev() == BootDev.pxe) {
bootCmd = _setPxeBootCommand;
} else {
throw new CloudRuntimeException("Unkonwn boot dev " + cmd.getBootDev());
}
String bootDev = cmd.getBootDev().name();
if (!doScript(bootCmd)) {
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "failed");
return new Answer(cmd, false, "Set " + _ip + " boot dev to " + bootDev + "failed");
}
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "Success");
return new Answer(cmd, true, "Set " + _ip + " boot dev to " + bootDev + "Success");
}
protected MaintainAnswer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd, false);
}
protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
return new PrepareForMigrationAnswer(cmd);
}
protected MigrateAnswer execute(MigrateCommand cmd) {
if (!doScript(_powerOffCommand)) {
return new MigrateAnswer(cmd, false, "IPMI power off failed", null);
}
return new MigrateAnswer(cmd, true, "success", null);
}
protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
return new CheckVirtualMachineAnswer(cmd, State.Stopped, null);
}
protected Answer execute(IpmiBootorResetCommand cmd) {
if (!doScript(_bootOrRebootCommand)) {
return new Answer(cmd, false, "IPMI boot or reboot failed");
}
return new Answer(cmd, true, "Success");
}
protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
return new CheckNetworkAnswer(cmd, true, "Success");
}
protected Answer execute(SecurityGroupRulesCmd cmd) {
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
return hc.call(cmd.getGuestIp(), cmd);
}
@Override
public Answer executeRequest(Command cmd) {
try {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else if (cmd instanceof StartCommand) {
return execute((StartCommand) cmd);
} else if (cmd instanceof StopCommand) {
return execute((StopCommand) cmd);
} else if (cmd instanceof RebootCommand) {
return execute((RebootCommand) cmd);
} else if (cmd instanceof IpmISetBootDevCommand) {
return execute((IpmISetBootDevCommand) cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand) cmd);
} else if (cmd instanceof PrepareForMigrationCommand) {
return execute((PrepareForMigrationCommand) cmd);
} else if (cmd instanceof MigrateCommand) {
return execute((MigrateCommand) cmd);
} else if (cmd instanceof CheckVirtualMachineCommand) {
return execute((CheckVirtualMachineCommand) cmd);
} else if (cmd instanceof IpmiBootorResetCommand) {
return execute((IpmiBootorResetCommand) cmd);
} else if (cmd instanceof SecurityGroupRulesCmd) {
return execute((SecurityGroupRulesCmd) cmd);
} else if (cmd instanceof CheckNetworkCommand) {
return execute((CheckNetworkCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
} catch (Throwable t) {
s_logger.debug(t.getMessage(), t);
return new Answer(cmd, false, t.getMessage());
}
}
protected boolean isPowerOn(String str) {
if (str.startsWith("Chassis Power is on")) {
return true;
} else if (str.startsWith("Chassis Power is off")) {
return false;
} else {
throw new CloudRuntimeException("Cannot parse IPMI power status " + str);
}
}
protected RebootAnswer execute(final RebootCommand cmd) {
if (!doScript(_rebootCommand)) {
return new RebootAnswer(cmd, "IPMI reboot failed", false);
}
return new RebootAnswer(cmd, "reboot succeeded", true);
}
protected StopAnswer execute(final StopCommand cmd) {
boolean success = false;
int count = 0;
Script powerOff = _powerOffCommand;
while (count < 10) {
if (!doScript(powerOff)) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
break;
}
if (!isPowerOn(interpreter.getLines())) {
success = true;
break;
} else {
powerOff = _forcePowerOffCommand;
}
count++;
}
return success ? new StopAnswer(cmd, "Success", 0, true) : new StopAnswer(cmd, "IPMI power off failed", false);
}
protected StartAnswer execute(StartCommand cmd) {
VirtualMachineTO vm = cmd.getVirtualMachine();
State state = State.Stopped;
try {
changeVmState(vm.getName(), State.Starting);
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
return new StartAnswer(cmd, "Cannot get current power status of " + _name);
}
if (isPowerOn(interpreter.getLines())) {
if (!doScript(_rebootCommand)) {
return new StartAnswer(cmd, "IPMI reboot failed");
}
} else {
if (!doScript(_powerOnCommand)) {
return new StartAnswer(cmd, "IPMI power on failed");
}
}
if (_isEchoScAgent) {
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
boolean echoRet = hc.echo(vm.getNics()[0].getIp(), TimeUnit.MINUTES.toMillis(30), TimeUnit.MINUTES.toMillis(1));
if (!echoRet) {
return new StartAnswer(cmd, String.format("Call security group agent on vm[%s] timeout", vm.getNics()[0].getIp()));
}
}
s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
state = State.Running;
_vmName = vm.getName();
return new StartAnswer(cmd);
} finally {
if (state != State.Stopped) {
changeVmState(vm.getName(), state);
} else {
removeVmState(vm.getName());
}
}
}
protected HashMap<String, State> deltaSync() {
final HashMap<String, State> changes = new HashMap<String, State>();
/*
* Disable sync until we find a way that only tracks status but not does
* action
*
* The scenario is: Baremetal will reboot host when creating template.
* Given most servers take a long time to boot up, there would be a
* period that mgmt server finds the host is stopped through fullsync.
* Then mgmt server updates database with marking the host as stopped,
* after that, the host comes up and full sync then indicates it's
* running. Because in database the host is already stopped, mgmt server
* sends out a stop command. As a result, creating image gets never
* happened.
*
* if (_vmName == null) { return null; }
*
* State newState = getVmState(); if (newState == null) {
* s_logger.warn("Cannot get power state of VM " + _vmName); return
* null; }
*
* final State oldState = removeVmState(_vmName); if (oldState == null)
* { changeVmState(_vmName, newState); changes.put(_vmName, newState); }
* else if (oldState == State.Starting) { if (newState == State.Running)
* { changeVmState(_vmName, newState); } else if (newState ==
* State.Stopped) { s_logger.debug("Ignoring vm " + _vmName +
* " because of a lag in starting the vm."); } } else if (oldState ==
* State.Migrating) {
* s_logger.warn("How can baremetal VM get into migrating state???"); }
* else if (oldState == State.Stopping) { if (newState == State.Stopped)
* { changeVmState(_vmName, newState); } else if (newState ==
* State.Running) { s_logger.debug("Ignoring vm " + _vmName +
* " because of a lag in stopping the vm. "); } } else if (oldState !=
* newState) { changeVmState(_vmName, newState); changes.put(_vmName,
* newState); }
*/
return changes;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
// derived resource should check if the PXE server is ready
s_logger.debug("Bare metal resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public void disconnected() {
}
@Override
public IAgentControl getAgentControl() {
return _agentControl;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
_agentControl = agentControl;
}
}

View File

@ -0,0 +1,173 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.net.URI;
import javax.ejb.Local;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IPAddressVO;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.guru.DirectPodBasedNetworkGuru;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = { NetworkGuru.class })
public class BaremetaNetworkGuru extends DirectPodBasedNetworkGuru {
private static final Logger s_logger = Logger.getLogger(BaremetaNetworkGuru.class);
@Inject
private HostDao _hostDao;
@Inject
DataCenterDao _dcDao;
@Inject
VlanDao _vlanDao;
@Inject
NetworkManager _networkMgr;
@Inject
IPAddressDao _ipAddressDao;
@Inject
NetworkOfferingDao _networkOfferingDao;
@Inject
PodVlanMapDao _podVlanDao;
@Override
public void reserve(NicProfile nic, Network network, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
if (dest.getHost().getHypervisorType() != HypervisorType.BareMetal) {
super.reserve(nic, network, vm, dest, context);
return;
}
HostVO host = _hostDao.findById(dest.getHost().getId());
_hostDao.loadDetails(host);
String intentIp = host.getDetail(ApiConstants.IP_ADDRESS);
if (intentIp == null) {
super.reserve(nic, network, vm, dest, context);
return;
}
String oldIp = nic.getIp4Address();
boolean getNewIp = false;
if (oldIp == null) {
getNewIp = true;
} else {
// we need to get a new ip address if we try to deploy a vm in a
// different pod
IPAddressVO ipVO = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), oldIp);
if (ipVO != null) {
PodVlanMapVO mapVO = _podVlanDao.listPodVlanMapsByVlan(ipVO.getVlanId());
if (mapVO.getPodId() != dest.getPod().getId()) {
Transaction txn = Transaction.currentTxn();
txn.start();
// release the old ip here
_networkMgr.markIpAsUnavailable(ipVO.getId());
_ipAddressDao.unassignIpAddress(ipVO.getId());
txn.commit();
nic.setIp4Address(null);
getNewIp = true;
}
}
}
if (getNewIp) {
// we don't set reservationStrategy to Create because we need this
// method to be called again for the case when vm fails to deploy in
// Pod1, and we try to redeploy it in Pod2
getBaremetalIp(nic, dest.getPod(), vm, network, intentIp);
}
DataCenter dc = _dcDao.findById(network.getDataCenterId());
nic.setDns1(dc.getDns1());
nic.setDns2(dc.getDns2());
/*
* Pod pod = dest.getPod(); Pair<String, Long> ip =
* _dcDao.allocatePrivateIpAddress(dest.getDataCenter().getId(),
* dest.getPod().getId(), nic.getId(), context.getReservationId(),
* intentIp); if (ip == null) { throw new
* InsufficientAddressCapacityException
* ("Unable to get a management ip address", Pod.class, pod.getId()); }
*
* nic.setIp4Address(ip.first());
* nic.setMacAddress(NetUtils.long2Mac(NetUtils
* .createSequenceBasedMacAddress(ip.second())));
* nic.setGateway(pod.getGateway()); nic.setFormat(AddressFormat.Ip4);
* String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
* nic.setNetmask(netmask);
* nic.setBroadcastType(BroadcastDomainType.Native);
* nic.setBroadcastUri(null); nic.setIsolationUri(null);
*/
s_logger.debug("Allocated a nic " + nic + " for " + vm);
}
private void getBaremetalIp(NicProfile nic, Pod pod, VirtualMachineProfile<? extends VirtualMachine> vm, Network network, String requiredIp)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
DataCenter dc = _dcDao.findById(pod.getDataCenterId());
if (nic.getIp4Address() == null) {
s_logger.debug(String.format("Requiring ip address: %s", nic.getIp4Address()));
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId(), requiredIp, false);
nic.setIp4Address(ip.getAddress().toString());
nic.setFormat(AddressFormat.Ip4);
nic.setGateway(ip.getGateway());
nic.setNetmask(ip.getNetmask());
if (ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase(Vlan.UNTAGGED)) {
nic.setIsolationUri(URI.create("ec2://" + Vlan.UNTAGGED));
nic.setBroadcastUri(URI.create("vlan://" + Vlan.UNTAGGED));
nic.setBroadcastType(BroadcastDomainType.Native);
}
nic.setReservationId(String.valueOf(ip.getVlanTag()));
nic.setMacAddress(ip.getMacAddress());
}
nic.setDns1(dc.getDns1());
nic.setDns2(dc.getDns2());
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.dc.Pod;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = NetworkElement.class)
public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProvider {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpElement.class);
private static final Map<Service, Map<Capability, String>> capabilities;
@Inject NicDao _nicDao;
@Inject BaremetalDhcpManager _dhcpMgr;
static {
Capability cap = new Capability(BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_CAPABITLITY);
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
baremetalCaps.put(cap, null);
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(Service.Dhcp, baremetalCaps);
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER;
}
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
Pod pod = dest.getPod();
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
return sc.find() != null;
}
return false;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
s_logger.debug("BaremetalDhcpElement can not handle networkoffering: " + offering.getName());
return false;
}
return true;
}
@Override
@DB
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
Host host = dest.getHost();
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
return false;
}
Transaction txn = Transaction.currentTxn();
txn.start();
nic.setMacAddress(host.getPrivateMacAddress());
NicVO vo = _nicDao.findById(nic.getId());
assert vo != null : "Where ths nic " + nic.getId() + " going???";
vo.setMacAddress(nic.getMacAddress());
_nicDao.update(vo.getId(), vo);
txn.commit();
return true;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean canEnableIndividualServices() {
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
return true;
}
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (vm.getHypervisorType() != HypervisorType.BareMetal || !canHandle(dest, network.getTrafficType(), network.getGuestType())) {
return false;
}
return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalDhcpManager extends Manager, PluggableService {
public static enum BaremetalDhcpType {
DNSMASQ,
DHCPD,
}
boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException;
BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd);
BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo);
List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd);
public static final String BAREMETAL_DHCP_SERVICE_CAPABITLITY = "BaremetalDhcp";
public static final String BAREMETAL_DHCP_SERVICE_PROPERTIES = "baremetaldhcp_commands.properties";
public static final Provider BAREMETAL_DHCP_SERVICE_PROVIDER = new Provider("BaremetalDhcpProvider", true);
}

View File

@ -0,0 +1,323 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalDhcpCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.baremetal.database.BaremetalDhcpDao;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.Network;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value = { BaremetalDhcpManager.class })
public class BaremetalDhcpManagerImpl implements BaremetalDhcpManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalDhcpManagerImpl.class);
protected String _name;
@Inject
DataCenterDao _dcDao;
@Inject
HostDao _hostDao;
@Inject
AgentManager _agentMgr;
@Inject
HostPodDao _podDao;
@Inject
UserVmDao _userVmDao;
@Inject
ResourceManager _resourceMgr;
@Inject
NicDao _nicDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject
BaremetalDhcpDao _extDhcpDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return true;
}
@Override
public String getName() {
return _name;
}
protected String getDhcpServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
@Override
public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile,
DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
Long zoneId = profile.getVirtualMachine().getDataCenterIdToDeployIn();
Long podId = profile.getVirtualMachine().getPodIdToDeployIn();
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.BaremetalDhcp, null, podId, zoneId);
if (hosts.size() == 0) {
throw new CloudRuntimeException("No external Dhcp found in zone " + zoneId + " pod " + podId);
}
if (hosts.size() > 1) {
throw new CloudRuntimeException("Something wrong, more than 1 external Dhcp found in zone " + zoneId + " pod " + podId);
}
HostVO h = hosts.get(0);
String dns = nic.getDns1();
if (dns == null) {
dns = nic.getDns2();
}
DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), profile.getVirtualMachine().getHostName(), dns,
nic.getGateway());
String errMsg = String.format("Set dhcp entry on external DHCP %1$s failed(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName());
// prepareBareMetalDhcpEntry(nic, dhcpCommand);
try {
Answer ans = _agentMgr.send(h.getId(), dhcpCommand);
if (ans.getResult()) {
s_logger.debug(String.format("Set dhcp entry on external DHCP %1$s successfully(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName()));
return true;
} else {
s_logger.debug(errMsg + " " + ans.getDetails());
throw new ResourceUnavailableException(errMsg, DataCenter.class, zoneId);
}
} catch (Exception e) {
s_logger.debug(errMsg, e);
throw new ResourceUnavailableException(errMsg + e.getMessage(), DataCenter.class, zoneId);
}
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
if (!(startup[0] instanceof StartupExternalDhcpCommand)) {
return null;
}
host.setType(Host.Type.BaremetalDhcp);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
@Override
@DB
public BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd) {
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
DataCenterVO zone = _dcDao.findById(zoneId);
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(),
BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName() + " is not enabled in the physical network: "
+ cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName()
+ " is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
HostPodVO pod = _podDao.findById(cmd.getPodId());
if (pod == null) {
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
}
List<HostVO> dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalDhcp, null, cmd.getPodId(), zoneId);
if (dhcps.size() != 0) {
throw new IllegalArgumentException("Already had a DHCP server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getDhcpServerGuid(Long.toString(zoneId) + "-" + Long.toString(cmd.getPodId()), "ExternalDhcp", ipAddress);
Map params = new HashMap<String, String>();
params.put("type", cmd.getDhcpType());
params.put("zone", Long.toString(zoneId));
params.put("pod", cmd.getPodId().toString());
params.put("ip", ipAddress);
params.put("username", cmd.getUsername());
params.put("password", cmd.getPassword());
params.put("guid", guid);
params.put("gateway", pod.getGateway());
String dns = zone.getDns1();
if (dns == null) {
dns = zone.getDns2();
}
params.put("dns", dns);
ServerResource resource = null;
try {
if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DNSMASQ.toString())) {
resource = new BaremetalDnsmasqResource();
resource.configure("Dnsmasq resource", params);
} else if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DHCPD.toString())) {
resource = new BaremetalDhcpdResource();
resource.configure("Dhcpd resource", params);
} else {
throw new CloudRuntimeException("Unsupport DHCP server type: " + cmd.getDhcpType());
}
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalDhcp, params);
if (dhcpServer == null) {
throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
}
BaremetalDhcpVO vo = new BaremetalDhcpVO();
vo.setDeviceType(cmd.getDhcpType());
vo.setHostId(dhcpServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPhysicalNetworkId(cmd.getPhysicalNetworkId());
vo.setPodId(cmd.getPodId());
Transaction txn = Transaction.currentTxn();
txn.start();
_extDhcpDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo) {
BaremetalDhcpResponse response = new BaremetalDhcpResponse();
response.setDeviceType(vo.getDeviceType());
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setProviderId(String.valueOf(vo.getNetworkServiceProviderId()));
return response;
}
@Override
public List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd) {
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
if (cmd.getDeviceType() != null) {
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, cmd.getDeviceType());
}
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalDhcpVO> vos = sc.list();
List<BaremetalDhcpResponse> responses = new ArrayList<BaremetalDhcpResponse>(vos.size());
for (BaremetalDhcpVO vo : vos) {
responses.add(generateApiResponse(vo));
}
return responses;
}
@Override
public List<Class<?>> getCommands() {
return null;
}
}

View File

@ -0,0 +1,174 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalDhcpCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDhcpResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpResourceBase.class);
String _name;
String _guid;
String _username;
String _password;
String _ip;
String _zoneId;
String _podId;
String _gateway;
String _dns;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_guid = (String)params.get("guid");
_ip = (String)params.get("ip");
_username = (String)params.get("username");
_password = (String)params.get("password");
_zoneId = (String)params.get("zone");
_podId = (String)params.get("pod");
_gateway = (String)params.get("gateway");
_dns = (String)params.get("dns");
if (_guid == null) {
throw new ConfigurationException("No Guid specified");
}
if (_zoneId == null) {
throw new ConfigurationException("No Zone specified");
}
if (_podId == null) {
throw new ConfigurationException("No Pod specified");
}
if (_ip == null) {
throw new ConfigurationException("No IP specified");
}
if (_username == null) {
throw new ConfigurationException("No username specified");
}
if (_password == null) {
throw new ConfigurationException("No password specified");
}
if (_gateway == null) {
throw new ConfigurationException("No gateway specified");
}
if (_dns == null) {
throw new ConfigurationException("No dns specified");
}
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public Type getType() {
return Type.BaremetalDhcp;
}
@Override
public StartupCommand[] initialize() {
StartupExternalDhcpCommand cmd = new StartupExternalDhcpCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public PingCommand getCurrentStatus(long id) {
//TODO: check server
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
protected ReadyAnswer execute(ReadyCommand cmd) {
s_logger.debug("External DHCP resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
@Override
public void disconnected() {
}
@Override
public IAgentControl getAgentControl() {
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
}
}

View File

@ -0,0 +1,71 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
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 BaremetalDhcpResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
private String id;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
private String physicalNetworkId;
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
private String providerId;
@SerializedName(ApiConstants.DHCP_SERVER_TYPE) @Param(description="name of the provider")
private String deviceType;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(String physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getProviderId() {
return providerId;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,139 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDhcpdResource extends BaremetalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpdResource.class);
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
com.trilead.ssh2.Connection sshConnection = null;
try {
super.configure(name, params);
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, "******"));
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
throw new ConfigurationException(
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
}
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dhcpd' ]")) {
throw new ConfigurationException("Cannot find dhcpd.conf /etc/dhcpd.conf at on " + _ip);
}
SCPClient scp = new SCPClient(sshConnection);
String editHosts = "scripts/network/exdhcp/dhcpd_edithosts.py";
String editHostsPath = Script.findScript("", editHosts);
if (editHostsPath == null) {
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
}
scp.put(editHostsPath, "/usr/bin/", "0755");
String prepareDhcpdScript = "scripts/network/exdhcp/prepare_dhcpd.sh";
String prepareDhcpdScriptPath = Script.findScript("", prepareDhcpdScript);
if (prepareDhcpdScriptPath == null) {
throw new ConfigurationException("Can not find prepare_dhcpd.sh at " + prepareDhcpdScriptPath);
}
scp.put(prepareDhcpdScriptPath, "/usr/bin/", "0755");
//TODO: tooooooooooooooo ugly here!!!
String[] ips = _ip.split("\\.");
ips[3] = "0";
StringBuffer buf = new StringBuffer();
int i;
for (i=0;i<ips.length-1;i++) {
buf.append(ips[i]).append(".");
}
buf.append(ips[i]);
String subnet = buf.toString();
String cmd = String.format("sh /usr/bin/prepare_dhcpd.sh %1$s", subnet);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("prepare Dhcpd at " + _ip + " failed, command:" + cmd);
}
s_logger.debug("Dhcpd resource configure successfully");
return true;
} catch (Exception e) {
s_logger.debug("Dhcpd resorce configure failed", e);
throw new ConfigurationException(e.getMessage());
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
Answer execute(DhcpEntryCommand cmd) {
com.trilead.ssh2.Connection sshConnection = null;
try {
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return new Answer(cmd, false, "ssh authenticate failed");
}
String addDhcp = String.format("python /usr/bin/dhcpd_edithosts.py %1$s %2$s %3$s %4$s %5$s %6$s",
cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName(), cmd.getDns(), cmd.getGateway(), cmd.getNextServer());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
return new Answer(cmd, false, "add Dhcp entry failed");
} else {
return new Answer(cmd);
}
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DhcpEntryCommand) {
return execute((DhcpEntryCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
}

View File

@ -0,0 +1,129 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDnsmasqResource extends BaremetalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalDnsmasqResource.class);
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
com.trilead.ssh2.Connection sshConnection = null;
try {
super.configure(name, params);
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, _password));
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
throw new ConfigurationException(
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, _password));
}
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dnsmasq' ]")) {
throw new ConfigurationException("Cannot find dnsmasq at /usr/sbin/dnsmasq on " + _ip);
}
SCPClient scp = new SCPClient(sshConnection);
String editHosts = "scripts/network/exdhcp/dnsmasq_edithosts.sh";
String editHostsPath = Script.findScript("", editHosts);
if (editHostsPath == null) {
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
}
scp.put(editHostsPath, "/usr/bin/", "0755");
String prepareDnsmasq = "scripts/network/exdhcp/prepare_dnsmasq.sh";
String prepareDnsmasqPath = Script.findScript("", prepareDnsmasq);
if (prepareDnsmasqPath == null) {
throw new ConfigurationException("Can not find script prepare_dnsmasq.sh at " + prepareDnsmasq);
}
scp.put(prepareDnsmasqPath, "/usr/bin/", "0755");
String prepareCmd = String.format("sh /usr/bin/prepare_dnsmasq.sh %1$s %2$s %3$s", _gateway, _dns, _ip);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, prepareCmd)) {
throw new ConfigurationException("prepare dnsmasq at " + _ip + " failed");
}
s_logger.debug("Dnsmasq resource configure successfully");
return true;
} catch (Exception e) {
s_logger.debug("Dnsmasq resorce configure failed", e);
throw new ConfigurationException(e.getMessage());
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
Answer execute(DhcpEntryCommand cmd) {
com.trilead.ssh2.Connection sshConnection = null;
try {
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return new Answer(cmd, false, "ssh authenticate failed");
}
String addDhcp = String.format("/usr/bin/dnsmasq_edithosts.sh %1$s %2$s %3$s", cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
return new Answer(cmd, false, "add Dhcp entry failed");
} else {
return new Answer(cmd);
}
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DhcpEntryCommand) {
return execute((DhcpEntryCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
}

View File

@ -0,0 +1,201 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartPxeResource.class);
private static final String _name = "BaremetalKickStartPxeResource";
String _tftpDir;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
_tftpDir = (String) params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
if (_tftpDir == null) {
throw new ConfigurationException("No tftp directory specified");
}
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
s_logger.debug(String.format("Trying to connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
"******"));
}
String cmd = String.format("[ -f /%1$s/pxelinux.0 ]", _tftpDir);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0 are here");
}
SCPClient scp = new SCPClient(sshConnection);
String prepareScript = "scripts/network/ping/prepare_kickstart_bootfile.py";
String prepareScriptPath = Script.findScript("", prepareScript);
if (prepareScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScriptPath);
}
scp.put(prepareScriptPath, "/usr/bin/", "0755");
String cpScript = "scripts/network/ping/prepare_kickstart_kernel_initrd.py";
String cpScriptPath = Script.findScript("", cpScript);
if (cpScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScriptPath);
}
scp.put(cpScriptPath, "/usr/bin/", "0755");
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
String userDataScriptPath = Script.findScript("", userDataScript);
if (userDataScriptPath == null) {
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
}
scp.put(userDataScriptPath, "/usr/bin/", "0755");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
private Answer execute(VmDataCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
List<String[]> vmData = cmd.getVmData();
StringBuilder sb = new StringBuilder();
for (String[] data : vmData) {
String folder = data[0];
String file = data[1];
String contents = (data[2] == null) ? "none" : data[2];
sb.append(cmd.getVmIpAddress());
sb.append(",");
sb.append(folder);
sb.append(",");
sb.append(file);
sb.append(",");
sb.append(contents);
sb.append(";");
}
String arg = StringUtils.stripEnd(sb.toString(), ";");
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "Failed to add user data, command:" + script);
}
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof PrepareKickstartPxeServerCommand) {
return execute((PrepareKickstartPxeServerCommand) cmd);
} else if (cmd instanceof VmDataCommand) {
return execute((VmDataCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
private Answer execute(PrepareKickstartPxeServerCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String copyTo = String.format("%s/%s", _tftpDir, cmd.getTemplateUuid());
String script = String.format("python /usr/bin/prepare_kickstart_kernel_initrd.py %s %s", cmd.getRepo(), copyTo);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
}
String kernelPath = String.format("%s/vmlinuz", cmd.getTemplateUuid());
String initrdPath = String.format("%s/initrd.img", cmd.getTemplateUuid());
script = String.format("python /usr/bin/prepare_kickstart_bootfile.py %s %s %s %s %s %s", _tftpDir, cmd.getMac(), kernelPath, initrdPath, cmd.getKsFile(), cmd.getMac());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
}
s_logger.debug("Prepare kickstart PXE server successfully");
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for kickstart server failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
}

View File

@ -0,0 +1,238 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.baremetal.database.BaremetalPxeDao;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.NetworkVO;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = BaremetalPxeService.class)
public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartServiceImpl.class);
@Inject
ResourceManager _resourceMgr;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject
HostDetailsDao _hostDetailsDao;
@Inject
BaremetalPxeDao _pxeDao;
@Inject
NetworkDao _nwDao;
@Inject
VMTemplateDao _tmpDao;
@Override
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
NetworkVO nwVO = _nwDao.findById(nic.getNetworkId());
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, nwVO.getPhysicalNetworkId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No kickstart PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
}
VMTemplateVO template = _tmpDao.findById(profile.getTemplateId());
try {
String tpl = profile.getTemplate().getUrl();
assert tpl != null : "How can a null template get here!!!";
String[] tpls = tpl.split(";");
assert tpls.length == 2 : "Template is not correctly encoded. " + tpl;
PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand();
cmd.setKsFile(tpls[0]);
cmd.setRepo(tpls[1]);
cmd.setMac(nic.getMacAddress());
cmd.setTemplateUuid(template.getUuid());
Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd);
if (!aws.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
return aws.getResult();
}
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
aws = _agentMgr.send(dest.getHost().getId(), bootCmd);
if (!aws.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
}
return aws.getResult();
} catch (Exception e) {
s_logger.warn("Cannot prepare PXE server", e);
return false;
}
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
// TODO Auto-generated method stub
return false;
}
@Override
@DB
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
AddBaremetalKickStartPxeCmd kcmd = (AddBaremetalKickStartPxeCmd)cmd;
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
List<HostVO> pxes = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId);
if (!pxes.isEmpty()) {
throw new IllegalArgumentException("Already had a PXE server zone: " + zoneId);
}
String tftpDir = kcmd.getTftpDir();
if (tftpDir == null) {
throw new IllegalArgumentException("No TFTP directory specified");
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getPxeServerGuid(Long.toString(zoneId), BaremetalPxeType.KICK_START.toString(), ipAddress);
ServerResource resource = null;
Map params = new HashMap<String, String>();
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
resource = new BaremetalKickStartPxeResource();
try {
resource.configure("KickStart PXE resource", params);
} catch (Exception e) {
throw new CloudRuntimeException(e.getMessage(), e);
}
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
if (pxeServer == null) {
throw new CloudRuntimeException("Cannot add PXE server as a host");
}
BaremetalPxeVO vo = new BaremetalPxeVO();
Transaction txn = Transaction.currentTxn();
vo.setHostId(pxeServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPhysicalNetworkId(kcmd.getPhysicalNetworkId());
vo.setDeviceType(BaremetalPxeType.KICK_START.toString());
txn.start();
_pxeDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
BaremetalPxeKickStartResponse response = new BaremetalPxeKickStartResponse();
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setPodId(String.valueOf(vo.getPodId()));
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
return response;
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalPxeVO> vos = sc.list();
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
for (BaremetalPxeVO vo : vos) {
responses.add(getApiResponse(vo));
}
return responses;
}
}

View File

@ -0,0 +1,260 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalPingPxeResource extends BaremetalPxeResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalPingPxeResource.class);
private static final String _name = "BaremetalPingPxeResource";
String _storageServer;
String _pingDir;
String _share;
String _dir;
String _tftpDir;
String _cifsUserName;
String _cifsPassword;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
_storageServer = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP);
_pingDir = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR);
_tftpDir = (String)params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
_cifsUserName = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME);
_cifsPassword = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD);
if (_podId == null) {
throw new ConfigurationException("No Pod specified");
}
if (_storageServer == null) {
throw new ConfigurationException("No stroage server specified");
}
if (_tftpDir == null) {
throw new ConfigurationException("No tftp directory specified");
}
if (_pingDir == null) {
throw new ConfigurationException("No PING directory specified");
}
if (_cifsUserName == null || _cifsUserName.equalsIgnoreCase("")) {
_cifsUserName = "xxx";
}
if (_cifsPassword == null || _cifsPassword.equalsIgnoreCase("")) {
_cifsPassword = "xxx";
}
String pingDirs[]= _pingDir.split("/");
if (pingDirs.length != 2) {
throw new ConfigurationException("PING dir should have format like myshare/direcotry, eg: windows/64bit");
}
_share = pingDirs[0];
_dir = pingDirs[1];
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
s_logger.debug(String.format("Trying to connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
"******"));
}
String cmd = String.format("[ -f /%1$s/pxelinux.0 ] && [ -f /%2$s/kernel ] && [ -f /%3$s/initrd.gz ] ", _tftpDir, _tftpDir, _tftpDir);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0, kernel initrd.gz are here");
}
SCPClient scp = new SCPClient(sshConnection);
String prepareScript = "scripts/network/ping/prepare_tftp_bootfile.py";
String prepareScriptPath = Script.findScript("", prepareScript);
if (prepareScriptPath == null) {
throw new ConfigurationException("Can not find prepare_tftp_bootfile.py at " + prepareScriptPath);
}
scp.put(prepareScriptPath, "/usr/bin/", "0755");
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
String userDataScriptPath = Script.findScript("", userDataScript);
if (userDataScriptPath == null) {
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
}
scp.put(userDataScriptPath, "/usr/bin/", "0755");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
protected PreparePxeServerAnswer execute(PreparePxeServerCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py restore %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new PreparePxeServerAnswer(cmd, "prepare PING at " + _ip + " failed, command:" + script);
}
s_logger.debug("Prepare Ping PXE server successfully");
return new PreparePxeServerAnswer(cmd);
} catch (Exception e){
s_logger.debug("Prepare PING pxe server failed", e);
return new PreparePxeServerAnswer(cmd, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
protected Answer execute(prepareCreateTemplateCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py backup %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare for creating template failed, command:" + script);
}
s_logger.debug("Prepare for creating template successfully");
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof PreparePxeServerCommand) {
return execute((PreparePxeServerCommand) cmd);
} else if (cmd instanceof prepareCreateTemplateCommand) {
return execute((prepareCreateTemplateCommand)cmd);
} else if (cmd instanceof VmDataCommand) {
return execute((VmDataCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
private Answer execute(VmDataCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
List<String[]> vmData = cmd.getVmData();
StringBuilder sb = new StringBuilder();
for (String[] data : vmData) {
String folder = data[0];
String file = data[1];
String contents = (data[2] == null) ? "none" : data[2];
sb.append(cmd.getVmIpAddress());
sb.append(",");
sb.append(folder);
sb.append(",");
sb.append(file);
sb.append(",");
sb.append(contents);
sb.append(";");
}
String arg = org.apache.commons.lang.StringUtils.stripEnd(sb.toString(), ";");
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "Failed to add user data, command:" + script);
}
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.Pod;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = NetworkElement.class)
public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
private static final Logger s_logger = Logger.getLogger(BaremetalPxeElement.class);
private static final Map<Service, Map<Capability, String>> capabilities;
@Inject BaremetalPxeManager _pxeMgr;;
@Inject VMInstanceDao _vmDao;
@Inject NicDao _nicDao;
static {
Capability cap = new Capability(BaremetalPxeManager.BAREMETAL_PXE_CAPABILITY);
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
baremetalCaps.put(cap, null);
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(BaremetalPxeManager.BAREMETAL_PXE_SERVICE, baremetalCaps);
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER;
}
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
Pod pod = dest.getPod();
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
return sc.find() != null;
}
return false;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
s_logger.debug("BaremetalPxeElement can not handle network offering: " + offering.getName());
return false;
}
return true;
}
@Override
@DB
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
return false;
}
VMInstanceVO vo = _vmDao.findById(vm.getId());
if (vo.getLastHostId() == null) {
Transaction txn = Transaction.currentTxn();
txn.start();
nic.setMacAddress(dest.getHost().getPrivateMacAddress());
NicVO nicVo = _nicDao.findById(nic.getId());
assert vo != null : "Where ths nic " + nic.getId() + " going???";
nicVo.setMacAddress(nic.getMacAddress());
_nicDao.update(nicVo.getId(), nicVo);
txn.commit();
/*This vm is just being created */
if (!_pxeMgr.prepare(vm, nic, dest, context)) {
throw new CloudRuntimeException("Cannot prepare pxe server");
}
}
return false;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean canEnableIndividualServices() {
return false;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalPxeKickStartResponse extends BaremetalPxeResponse {
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
private String tftpDir;
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,65 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.HostVO;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalPxeManager extends Manager, PluggableService {
public enum BaremetalPxeType {
PING,
KICK_START,
}
boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context);
boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
BaremetalPxeType getPxeServerType(HostVO host);
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> vm);
public static final Network.Service BAREMETAL_PXE_SERVICE = new Network.Service("BaremetalPxeService");
public static final String BAREMETAL_PXE_CAPABILITY = "BaremetalPxe";
public static final String BAREMETAL_PXE_SERVICE_PROPERTIES = "baremetalpxe_commands.properties";
public static final Provider BAREMETAL_PXE_SERVICE_PROVIDER = new Provider("BaremetalPxeProvider", true);;
public static final Provider BAREMETAL_USERDATA_PROVIDER = new Provider("BaremetaUserdataProvider", true);
}

View File

@ -0,0 +1,242 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value = {BaremetalPxeManager.class})
public class BaremetalPxeManagerImpl implements BaremetalPxeManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalPxeManagerImpl.class);
protected String _name;
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject ResourceManager _resourceMgr;
@Inject(adapter=BaremetalPxeService.class)
protected Adapters<BaremetalPxeService> _services;
@Inject UserVmDao _vmDao;
@Inject ServiceOfferingDao _serviceOfferingDao;
@Inject NicDao _nicDao;
@Inject ConfigurationDao _configDao;
@Inject PhysicalNetworkDao _phynwDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return true;
}
@Override
public String getName() {
return _name;
}
protected BaremetalPxeService getServiceByType(String type) {
BaremetalPxeService _service;
_service = _services.get(type);
if (_service == null) {
throw new CloudRuntimeException("Cannot find PXE service for " + type);
}
return _service;
}
@Override
public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
//TODO: select type from template
BaremetalPxeType type = BaremetalPxeType.KICK_START;
return getServiceByType(type.toString()).prepare(profile, nic, dest, context);
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
//TODO: select type from template
BaremetalPxeType type = BaremetalPxeType.PING;
return getServiceByType(type.toString()).prepareCreateTemplate(pxeServerId, vm, templateUrl);
}
@Override
public BaremetalPxeType getPxeServerType(HostVO host) {
if (host.getResource().equalsIgnoreCase(BaremetalPingPxeResource.class.getName())) {
return BaremetalPxeType.PING;
} else {
throw new CloudRuntimeException("Unkown PXE server resource " + host.getResource());
}
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
if (!(startup[0] instanceof StartupPxeServerCommand)) {
return null;
}
host.setType(Host.Type.BaremetalPxe);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
@Override
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
return getServiceByType(cmd.getDeviceType()).addPxeServer(cmd);
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
return getServiceByType(vo.getDeviceType()).getApiResponse(vo);
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
return getServiceByType(BaremetalPxeManager.BaremetalPxeType.PING.toString()).listPxeServers(cmd);
}
@Override
public boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> profile) {
UserVmVO vm = (UserVmVO) profile.getVirtualMachine();
_vmDao.loadDetails(vm);
String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText();
String zoneName = _dcDao.findById(vm.getDataCenterIdToDeployIn()).getName();
NicVO nvo = _nicDao.findById(nic.getId());
VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName());
cmd.addVmData("userdata", "user-data", vm.getUserData());
cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering));
cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
cmd.addVmData("metadata", "local-ipv4", nic.getIp4Address());
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
cmd.addVmData("metadata", "public-ipv4", nic.getIp4Address());
cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
cmd.addVmData("metadata", "instance-id", String.valueOf(vm.getId()));
cmd.addVmData("metadata", "vm-id", String.valueOf(vm.getInstanceName()));
cmd.addVmData("metadata", "public-keys", null);
String cloudIdentifier = _configDao.getValue("cloud.identifier");
if (cloudIdentifier == null) {
cloudIdentifier = "";
} else {
cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
}
cmd.addVmData("metadata", "cloud-identifier", cloudIdentifier);
List<PhysicalNetworkVO> phys = _phynwDao.listByZone(vm.getDataCenterIdToDeployIn());
if (phys.isEmpty()) {
throw new CloudRuntimeException(String.format("Cannot find physical network in zone %s", vm.getDataCenterIdToDeployIn()));
}
if (phys.size() > 1) {
throw new CloudRuntimeException(String.format("Baremetal only supports one physical network in zone, but zone %s has %s physical networks", vm.getDataCenterIdToDeployIn(), phys.size()));
}
PhysicalNetworkVO phy = phys.get(0);
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
//TODO: handle both kickstart and PING
//sc.addAnd(sc.getEntity().getPodId(), Op.EQ, vm.getPodIdToDeployIn());
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, phy.getId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No PXE server found in pod: " + vm.getPodIdToDeployIn() + ", you need to add it before starting VM");
}
try {
Answer ans = _agentMgr.send(pxeVo.getHostId(), cmd);
if (!ans.getResult()) {
s_logger.debug(String.format("Add userdata to vm:%s failed because %s", vm.getInstanceName(), ans.getDetails()));
return false;
} else {
return true;
}
} catch (Exception e) {
s_logger.debug(String.format("Add userdata to vm:%s failed", vm.getInstanceName()), e);
return false;
}
}
@Override
public List<Class<?>> getCommands() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,59 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalPxePingResponse extends BaremetalPxeResponse {
@SerializedName(ApiConstants.PING_STORAGE_SERVER_IP) @Param(description="PING storage server ip")
private String pingStorageServerIp;
@SerializedName(ApiConstants.PING_DIR) @Param(description="Root directory on PING storage server")
private String pingDir;
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
private String tftpDir;
public String getPingStorageServerIp() {
return pingStorageServerIp;
}
public void setPingStorageServerIp(String pingStorageServerIp) {
this.pingStorageServerIp = pingStorageServerIp;
}
public String getPingDir() {
return pingDir;
}
public void setPingDir(String pingDir) {
this.pingDir = pingDir;
}
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,157 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
public class BaremetalPxeResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BaremetalPxeResourceBase.class);
String _name;
String _guid;
String _username;
String _password;
String _ip;
String _zoneId;
String _podId;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_guid = (String)params.get(BaremetalPxeService.PXE_PARAM_GUID);
_ip = (String)params.get(BaremetalPxeService.PXE_PARAM_IP);
_username = (String)params.get(BaremetalPxeService.PXE_PARAM_USERNAME);
_password = (String)params.get(BaremetalPxeService.PXE_PARAM_PASSWORD);
_zoneId = (String)params.get(BaremetalPxeService.PXE_PARAM_ZONE);
_podId = (String)params.get(BaremetalPxeService.PXE_PARAM_POD);
if (_guid == null) {
throw new ConfigurationException("No Guid specified");
}
if (_zoneId == null) {
throw new ConfigurationException("No Zone specified");
}
if (_ip == null) {
throw new ConfigurationException("No IP specified");
}
if (_username == null) {
throw new ConfigurationException("No username specified");
}
if (_password == null) {
throw new ConfigurationException("No password specified");
}
return true;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
s_logger.debug("Pxe resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return _name;
}
@Override
public Type getType() {
return Type.BaremetalPxe;
}
@Override
public StartupCommand[] initialize() {
StartupPxeServerCommand cmd = new StartupPxeServerCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public PingCommand getCurrentStatus(long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void disconnected() {
// TODO Auto-generated method stub
}
@Override
public IAgentControl getAgentControl() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
// TODO Auto-generated method stub
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
}

View File

@ -0,0 +1,71 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
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 BaremetalPxeResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
private String id;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
private String physicalNetworkId;
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
private String providerId;
@SerializedName(ApiConstants.POD_ID) @Param(description="pod id where the device is in")
private String podId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(String physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getProviderId() {
return providerId;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public String getPodId() {
return podId;
}
public void setPodId(String podId) {
this.podId = podId;
}
}

View File

@ -0,0 +1,61 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalPxeService extends Adapter {
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context);
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
public static final String PXE_PARAM_TYPE = "type";
public static final String PXE_PARAM_ZONE = "zone";
public static final String PXE_PARAM_POD = "pod";
public static final String PXE_PARAM_IP = "ip";
public static final String PXE_PARAM_GUID = "guid";
public static final String PXE_PARAM_TFTP_DIR = "tftpDir";
public static final String PXE_PARAM_USERNAME = "username";
public static final String PXE_PARAM_PASSWORD = "password";
public static final String PXE_PARAM_PING_STORAGE_SERVER_IP = "pingStorageServerIp";
public static final String PXE_PARAM_PING_ROOT_DIR = "pingDir";
public static final String PXE_PARAM_PING_STORAGE_SERVER_USERNAME = "pingStorageServerUserName";
public static final String PXE_PARAM_PING_STORAGE_SERVER_PASSWORD = "pingStorageServerPassword";
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import com.cloud.baremetal.manager.BaremetalManager;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.offering.NetworkOffering;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = NetworkElement.class)
public class BaremetalUserdataElement extends AdapterBase implements NetworkElement, UserDataServiceProvider {
private static Map<Service, Map<Capability, String>> capabilities;
@Inject
private BaremetalPxeManager pxeMgr;
static {
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(Service.UserData, null);
}
private boolean canHandle(DeployDestination dest) {
if (dest.getDataCenter().getNetworkType() == NetworkType.Basic && dest.getHost().getHypervisorType() == HypervisorType.BareMetal) {
return true;
}
return false;
}
@Override
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (!canHandle(dest)) {
return false;
}
if (vm.getType() != VirtualMachine.Type.User) {
return false;
}
return pxeMgr.addUserData(nic, (VirtualMachineProfile<UserVm>) vm);
}
@Override
public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, String SSHPublicKey) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalPxeManager.BAREMETAL_USERDATA_PROVIDER;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean canEnableIndividualServices() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,102 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
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;
public class ListBaremetalDhcpCmd extends BaseListCmd {
private static final Logger s_logger = Logger.getLogger(ListBaremetalDhcpCmd.class);
private static final String s_name = "listexternaldhcpresponse";
@PlugService BaremetalDhcpManager _dhcpMgr;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "DHCP server device ID")
private Long id;
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
private Long podId;
@Parameter(name = ApiConstants.DHCP_SERVER_TYPE, type = CommandType.STRING, description = "Type of DHCP device")
private String deviceType;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
ListResponse<BaremetalDhcpResponse> response = new ListResponse<BaremetalDhcpResponse>();
List<BaremetalDhcpResponse> dhcpResponses = _dhcpMgr.listBaremetalDhcps(this);
response.setResponses(dhcpResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.debug("Exception happend while executing ListBaremetalDhcpCmd");
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
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;
public class ListBaremetalPxePingServersCmd extends BaseListCmd {
private static final Logger s_logger = Logger.getLogger(ListBaremetalPxePingServersCmd.class);
private static final String s_name = "listpingpxeserverresponse";
@PlugService
BaremetalPxeManager _pxeMgr;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "Ping pxe server device ID")
private Long id;
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
private Long podId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
ListResponse<BaremetalPxeResponse> response = new ListResponse<BaremetalPxeResponse>();
List<BaremetalPxeResponse> pxeResponses = _pxeMgr.listPxeServers(this);
response.setResponses(pxeResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.debug("Exception happend while executing ListPingPxeServersCmd" ,e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import com.cloud.agent.api.Command;
public class PrepareKickstartPxeServerCommand extends Command {
private String ksFile;
private String repo;
private String templateUuid;
private String mac;
private String ksDevice;
@Override
public boolean executeInSequence() {
return true;
}
public String getKsFile() {
return ksFile;
}
public void setKsFile(String ksFile) {
this.ksFile = ksFile;
}
public String getRepo() {
return repo;
}
public void setRepo(String repo) {
this.repo = repo;
}
public String getTemplateUuid() {
return templateUuid;
}
public void setTemplateUuid(String templateUuid) {
this.templateUuid = templateUuid;
}
public String getMac() {
return mac;
}
public void setMac(String mac) {
this.mac = mac;
}
public String getKsDevice() {
return ksDevice;
}
public void setKsDevice(String ksDevice) {
this.ksDevice = ksDevice;
}
}

View File

@ -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.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
package com.cloud.baremetal.networkservice;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.SecurityGroupRulesCmd;
public class SecurityGroupHttpClient {
public Answer call(String guestIp, SecurityGroupRulesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
public boolean echo(String ip, long millis, long millis2) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -153,6 +153,7 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.PortForwardingRuleTO;
@ -190,6 +191,7 @@ import com.cloud.network.HAProxyConfigurator;
import com.cloud.network.LoadBalancerConfigurator; import com.cloud.network.LoadBalancerConfigurator;
import com.cloud.network.Networks; import com.cloud.network.Networks;
import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.rules.FirewallRule;
import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResource;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
import com.cloud.storage.Storage; import com.cloud.storage.Storage;
@ -618,10 +620,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) { protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
String controlIp = getRouterSshControlIp(cmd); String controlIp = getRouterSshControlIp(cmd);
String[] results = new String[cmd.getRules().length]; String[] results = new String[cmd.getRules().length];
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
String[][] rules = cmd.generateFwRules(); String[][] rules = cmd.generateFwRules();
String args = ""; String args = "";
args += " -F "; args += " -F ";
if (trafficType == FirewallRule.TrafficType.Egress){
args+= " -E ";
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0]; String[] fwRules = rules[0];
if (fwRules.length > 0) { if (fwRules.length > 0) {
@ -634,13 +642,28 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
try { try {
VmwareManager mgr = getServiceContext().getStockObject( VmwareManager mgr = getServiceContext().getStockObject(
VmwareManager.CONTEXT_STOCK_NAME); VmwareManager.CONTEXT_STOCK_NAME);
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp,
Pair<Boolean, String> result = null;
if (trafficType == FirewallRule.TrafficType.Egress){
result = SshHelper.sshExecute(controlIp,
DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
null, "/root/firewallRule_egress.sh " + args);
} else {
result = SshHelper.sshExecute(controlIp,
DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
null, "/root/firewall_rule.sh " + args); null, "/root/firewall_rule.sh " + args);
}
if (s_logger.isDebugEnabled()) if (s_logger.isDebugEnabled()) {
if (trafficType == FirewallRule.TrafficType.Egress){
s_logger.debug("Executing script on domain router " + controlIp
+ ": /root/firewallRule_egress.sh " + args);
} else {
s_logger.debug("Executing script on domain router " + controlIp s_logger.debug("Executing script on domain router " + controlIp
+ ": /root/firewall_rule.sh " + args); + ": /root/firewall_rule.sh " + args);
}
}
if (!result.first()) { if (!result.first()) {
s_logger.error("SetFirewallRulesCommand failure on setting one rule. args: " s_logger.error("SetFirewallRulesCommand failure on setting one rule. args: "

View File

@ -53,6 +53,8 @@ import javax.ejb.Local;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import com.cloud.agent.api.to.*;
import com.cloud.network.rules.FirewallRule;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -7182,14 +7184,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
String callResult; String callResult;
Connection conn = getConnection(); Connection conn = getConnection();
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
if (routerIp == null) { if (routerIp == null) {
return new SetFirewallRulesAnswer(cmd, false, results); return new SetFirewallRulesAnswer(cmd, false, results);
} }
String[][] rules = cmd.generateFwRules(); String[][] rules = cmd.generateFwRules();
String args = ""; String args = "";
args += routerIp + " -F "; args += routerIp + " -F";
if (trafficType == FirewallRule.TrafficType.Egress){
args+= " -E";
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0]; String[] fwRules = rules[0];
if (fwRules.length > 0) { if (fwRules.length > 0) {

View File

@ -277,6 +277,7 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.MultipleIps, "true"); firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress");
capabilities.put(Service.Firewall, firewallCapabilities); capabilities.put(Service.Firewall, firewallCapabilities);
// Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work // Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work

View File

@ -42,6 +42,7 @@
<module>hypervisors/xen</module> <module>hypervisors/xen</module>
<module>hypervisors/kvm</module> <module>hypervisors/kvm</module>
<module>hypervisors/simulator</module> <module>hypervisors/simulator</module>
<module>hypervisors/baremetal</module>
<module>network-elements/elastic-loadbalancer</module> <module>network-elements/elastic-loadbalancer</module>
<module>network-elements/ovs</module> <module>network-elements/ovs</module>
<module>network-elements/nicira-nvp</module> <module>network-elements/nicira-nvp</module>

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