Repository: cloudstack
Updated Branches:
refs/heads/master d315a5e2c -> b11e3bc60
CLOUDSTACK-6278
Baremetal Advanced Networking support
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b11e3bc6
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b11e3bc6
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b11e3bc6
Branch: refs/heads/master
Commit: b11e3bc60a03f02af8731404c4929bed50136c03
Parents: bc2ec23
Author: Frank Zhang <[email protected]>
Authored: Thu Sep 18 16:40:04 2014 -0700
Committer: Frank Zhang <[email protected]>
Committed: Thu Sep 18 16:54:37 2014 -0700
----------------------------------------------------------------------
api/src/com/cloud/event/EventTypes.java | 1 +
.../baremetal/manager/BaremetalManager.java | 3 +
.../baremetal/manager/BaremetalManagerImpl.java | 42 ++++++++++
.../networkservice/BareMetalResourceBase.java | 45 ++++++++++
.../BaremetalKickStartServiceImpl.java | 9 +-
.../BaremetalProvisionDoneNotificationCmd.java | 87 ++++++++++++++++++++
server/src/com/cloud/configuration/Config.java | 36 ++++----
.../VirtualNetworkApplianceManagerImpl.java | 4 +-
8 files changed, 210 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java
b/api/src/com/cloud/event/EventTypes.java
index 7477152..3a1d58a 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -454,6 +454,7 @@ public class EventTypes {
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD =
"PHYSICAL.PXE.ADD";
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE =
"PHYSICAL.PXE.DELETE";
public static final String EVENT_BAREMETAL_RCT_ADD = "BAREMETAL.RCT.ADD";
+ public static final String EVENT_BAREMETAL_PROVISION_DONE =
"BAREMETAL.PROVISION.DONE";
public static final String EVENT_AFFINITY_GROUP_CREATE = "AG.CREATE";
public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE";
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
----------------------------------------------------------------------
diff --git
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
index 5db29d2..629153a 100755
---
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
+++
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
@@ -20,9 +20,12 @@ package com.cloud.baremetal.manager;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
+import org.apache.cloudstack.api.BaremetalProvisionDoneNotificationCmd;
public interface BaremetalManager extends Manager, PluggableService {
public static final String EchoSecurityGroupAgent =
"EchoSecurityGroupAgent";
public static final String ExternalBaremetalSystemUrl =
"ExternalBaremetalSystemUrl";
public static final String DO_PXE = "doPxe";
+
+ void notifyProvisionDone(BaremetalProvisionDoneNotificationCmd cmd);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
----------------------------------------------------------------------
diff --git
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
index f6a4113..d4a75dc 100755
---
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
+++
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
@@ -26,6 +26,12 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import com.cloud.utils.db.QueryBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.api.BaremetalProvisionDoneNotificationCmd;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.AddBaremetalHostCmd;
@@ -45,6 +51,8 @@ public class BaremetalManagerImpl extends ManagerBase
implements BaremetalManage
@Inject
protected HostDao _hostDao;
+ @Inject
+ protected VMInstanceDao vmDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws
ConfigurationException {
@@ -107,6 +115,40 @@ public class BaremetalManagerImpl extends ManagerBase
implements BaremetalManage
public List<Class<?>> getCommands() {
List<Class<?>> cmds = new ArrayList<Class<?>>();
cmds.add(AddBaremetalHostCmd.class);
+ cmds.add(BaremetalProvisionDoneNotificationCmd.class);
return cmds;
}
+
+ @Override
+ public void notifyProvisionDone(BaremetalProvisionDoneNotificationCmd cmd)
{
+ QueryBuilder<HostVO> hq = QueryBuilder.create(HostVO.class);
+ hq.and(hq.entity().getPrivateMacAddress(), SearchCriteria.Op.EQ,
cmd.getMac());
+ HostVO host = hq.find();
+ if (host == null) {
+ throw new CloudRuntimeException(String.format("cannot find
host[mac:%s]", cmd.getMac()));
+ }
+
+ _hostDao.loadDetails(host);
+ String vmName = host.getDetail("vmName");
+ if (vmName == null) {
+ throw new CloudRuntimeException(String.format("cannot find any
baremetal instance running on host[mac:%s]", cmd.getMac()));
+ }
+
+ QueryBuilder<VMInstanceVO> vmq =
QueryBuilder.create(VMInstanceVO.class);
+ vmq.and(vmq.entity().getInstanceName(), SearchCriteria.Op.EQ, vmName);
+ VMInstanceVO vm = vmq.find();
+
+ if (vm == null) {
+ throw new CloudRuntimeException(String.format("cannot find
baremetal instance[name:%s]", vmName));
+ }
+
+ if (State.Starting != vm.getState()) {
+ throw new CloudRuntimeException(String.format("baremetal
instance[name:%s, state:%s] is not in state of Starting", vmName,
vm.getState()));
+ }
+
+ vm.setState(State.Running);
+ vmDao.update(vm.getId(), vm);
+ s_logger.debug(String.format("received baremetal provision done
notification for vm[id:%s name:%s] running on host[mac:%s, ip:%s]",
+ vm.getId(), vm.getInstanceName(), host.getPrivateMacAddress(),
host.getPrivateIpAddress()));
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
----------------------------------------------------------------------
diff --git
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
index 49a935a..26f42be 100755
---
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
+++
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
@@ -61,12 +61,15 @@ import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.ServerResource;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.QueryBuilder;
+import com.cloud.utils.db.SearchCriteria;
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.PowerState;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.api.ApiConstants;
@@ -109,6 +112,8 @@ public class BareMetalResourceBase extends ManagerBase
implements ServerResource
protected Script2 _bootOrRebootCommand;
protected String _vmName;
protected int ipmiRetryTimes = 5;
+ protected boolean provisionDoneNotificationOn = false;
+ protected int isProvisionDoneNotificationTimeout = 1800;
protected ConfigurationDao configDao;
protected VMInstanceDao vmDao;
@@ -183,6 +188,13 @@ public class BareMetalResourceBase extends ManagerBase
implements ServerResource
s_logger.debug(e.getMessage(), e);
}
+ try {
+ provisionDoneNotificationOn =
Boolean.valueOf(configDao.getValue(Config.BaremetalProvisionDoneNotificationEnabled.key()));
+ isProvisionDoneNotificationTimeout =
Integer.valueOf(configDao.getValue(Config.BaremetalProvisionDoneNotificationTimeout.key()));
+ } catch (Exception e) {
+ s_logger.debug(e.getMessage(), e);
+ }
+
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
@@ -579,6 +591,39 @@ public class BareMetalResourceBase extends ManagerBase
implements ServerResource
}
}
+ if (provisionDoneNotificationOn) {
+ QueryBuilder<VMInstanceVO> q =
QueryBuilder.create(VMInstanceVO.class);
+ q.and(q.entity().getInstanceName(), SearchCriteria.Op.EQ,
vm.getName());
+ VMInstanceVO vmvo = q.find();
+
+ if (vmvo.getLastHostId() == null) {
+ // this is new created vm
+ long timeout = System.currentTimeMillis() +
TimeUnit.SECONDS.toMillis(isProvisionDoneNotificationTimeout);
+ while (timeout > System.currentTimeMillis()) {
+ try {
+ TimeUnit.SECONDS.sleep(5);
+ } catch (InterruptedException e) {
+ s_logger.warn(e.getMessage(), e);
+ }
+
+ q = QueryBuilder.create(VMInstanceVO.class);
+ q.and(q.entity().getInstanceName(), SearchCriteria.Op.EQ,
vm.getName());
+ vmvo = q.find();
+ if (vmvo == null) {
+ return new StartAnswer(cmd, String.format("cannot find
vm[name:%s] while waiting for baremtal provision done notification",
vm.getName()));
+ }
+
+ if (VirtualMachine.State.Running == vmvo.getState()) {
+ return new StartAnswer(cmd);
+ }
+
+ s_logger.debug(String.format("still wait for baremetal
provision done notification for vm[name:%s], current vm state is %s",
vmvo.getInstanceName(), vmvo.getState()));
+ }
+
+ return new StartAnswer(cmd, String.format("timeout after %s
seconds, no baremetal provision done notification received. vm[name:%s] failed
to start", isProvisionDoneNotificationTimeout, vm.getName()));
+ }
+ }
+
s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
_vmName = vm.getName();
return new StartAnswer(cmd);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
----------------------------------------------------------------------
diff --git
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
index 2e236c2..3b88ca6 100755
---
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
+++
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
@@ -30,6 +30,7 @@ import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
+import com.cloud.configuration.Config;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd;
@@ -218,6 +219,11 @@ public class BaremetalKickStartServiceImpl extends
BareMetalPxeServiceBase imple
throw new CloudRuntimeException(String.format("cannot find
management nic on virtual router[id:%s]", vr.getId()));
}
+ String internalServerIp =
_configDao.getValue(Config.BaremetalInternalStorageServer.key());
+ if (internalServerIp == null) {
+ throw new CloudRuntimeException(String.format("please specify
'baremetal.internal.storage.server.ip', which is the http server/nfs server
storing kickstart files and ISO files, in global setting"));
+ }
+
List<String> tuple = parseKickstartUrl(profile);
String cmd = String.format("/usr/bin/prepare_pxe.sh %s %s %s %s %s
%s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
String.format("01-%s", nic.getMacAddress().replaceAll(":",
"-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase());
@@ -227,8 +233,7 @@ public class BaremetalKickStartServiceImpl extends
BareMetalPxeServiceBase imple
throw new CloudRuntimeException(String.format("failed preparing
PXE in virtual router[id:%s], because %s", vr.getId(), ret.second()));
}
- //String internalServerIp =
_configDao.getValue(Config.BaremetalInternalStorageServer.key());
- String internalServerIp = "10.223.110.231";
+ //String internalServerIp = "10.223.110.231";
cmd = String.format("/usr/bin/baremetal_snat.sh %s %s %s",
mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s],
cmd: %s", mgmtNic.getIp4Address(), cmd));
ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root",
getSystemVMKeyFile(), null, cmd);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
----------------------------------------------------------------------
diff --git
a/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
b/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
new file mode 100755
index 0000000..9cb4b57
--- /dev/null
+++
b/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
@@ -0,0 +1,87 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+package org.apache.cloudstack.api;
+
+import com.cloud.baremetal.manager.BaremetalManager;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import javax.inject.Inject;
+import org.apache.log4j.Logger;
+
+/**
+ * Created by frank on 9/17/14.
+ */
+@APICommand(name = "notifyBaremetalProvisionDone", description = "Notify
provision has been done on a host. This api is for baremetal virtual router
service, not for end user", responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
authorized = {RoleType.User})
+public class BaremetalProvisionDoneNotificationCmd extends BaseAsyncCmd {
+ public static final Logger s_logger =
Logger.getLogger(BaremetalProvisionDoneNotificationCmd.class);
+ private static final String s_name = "baremetalprovisiondone";
+
+ @Inject
+ private BaremetalManager bmMgr;
+
+ @Parameter(name="mac", required = true, description = "mac of the nic used
for provision")
+ private String mac;
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_BAREMETAL_PROVISION_DONE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "notify management server that baremetal provision has been
done on a host";
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
InsufficientCapacityException, ServerApiException,
ConcurrentOperationException, ResourceAllocationException,
NetworkRuleConflictException {
+ try {
+ bmMgr.notifyProvisionDone(this);
+ this.setResponseObject(new SuccessResponse(getCommandName()));
+ } catch (Exception e) {
+ s_logger.warn(String.format("unable to notify baremetal provision
done[mac:%s]", mac), e);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
e.getMessage());
+ }
+ }
+
+ public String getMac() {
+ return mac;
+ }
+
+ public void setMac(String mac) {
+ this.mac = mac;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java
b/server/src/com/cloud/configuration/Config.java
index 1f15d39..9309e3a 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -1849,29 +1849,37 @@ public enum Config {
"The maximum number of retrying times to search for an available
IPv6 address in the table",
null),
- BaremetalEnableCompleteNotification(
+ BaremetalInternalStorageServer(
+ "Advanced",
+ ManagementServer.class,
+ String.class,
+ "baremetal.internal.storage.server.ip",
+ null,
+ "the ip address of server that stores kickstart file, kernel,
initrd, ISO for advanced networking baremetal provisioning",
+ null),
+ BaremetalProvisionDoneNotificationEnabled(
"Advanced",
ManagementServer.class,
Boolean.class,
- "baremetal.provision.done.notification",
- "false",
- "Enable provision done notification through virtual router",
+ "baremetal.provision.done.notification.enabled",
+ "true",
+ "whether to enable baremetal provison done notification",
null),
- BaremetalPeerHypervisorType(
+ BaremetalProvisionDoneNotificationTimeout(
"Advanced",
ManagementServer.class,
- String.class,
- "baremetal.peer.hypervisor.type",
- "Vmware",
- "Hypervisor[Xenserver/KVM/VMWare] used to spring up virtual router
for baremetal instances. The cluster having this hypervisor type must be in the
same zone with baremetal cluster",
+ Integer.class,
+ "baremetal.provision.done.notification.timeout",
+ "1800",
+ "the max time to wait before treating a baremetal provision as
failure if no provision done notification is not received, in secs",
null),
- BaremetalInternalStorageServer(
+ BaremetalProvisionDoneNotificationPort(
"Advanced",
ManagementServer.class,
- String.class,
- "baremetal.internal.storage.server.ip",
- null,
- "the ip address of server that stores kickstart file, kernel,
initrd, ISO for advanced networking baremetal provisioning",
+ Integer.class,
+ "baremetal.provision.done.notification.port",
+ "8080",
+ "the port that listens baremetal provision done notification.
Should be the same to port management server listening on for now. Please
change it to management server port if it's not default 8080",
null),
ExternalBaremetalSystemUrl(
"Advanced",
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b11e3bc6/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git
a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index c95867e..898aec9 100755
---
a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++
b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -2323,7 +2323,7 @@ VirtualMachineGuru, Listener, Configurable,
StateListener<State, VirtualMachine.
}
}
- if
(Boolean.valueOf(_configDao.getValue("baremetal.provision.done.notification")))
{
+ if
(Boolean.valueOf(_configDao.getValue(Config.BaremetalProvisionDoneNotificationEnabled.key())))
{
QueryBuilder<UserVO> acntq = QueryBuilder.create(UserVO.class);
acntq.and(acntq.entity().getUsername(), SearchCriteria.Op.EQ,
"baremetal-system-account");
UserVO user = acntq.find();
@@ -2332,6 +2332,8 @@ VirtualMachineGuru, Listener, Configurable,
StateListener<State, VirtualMachine.
} else {
buf.append(String.format("
baremetalnotificationsecuritykey=%s", user.getSecretKey()));
buf.append(String.format(" baremetalnotificationapikey=%s",
user.getApiKey()));
+ buf.append("
host=").append(ApiServiceConfiguration.ManagementHostIPAdr.value());
+ buf.append("
port=").append(_configDao.getValue(Config.BaremetalProvisionDoneNotificationPort.key()));
}
}