mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge branch 'master' of ssh://git.cloud.com/var/lib/git/cloudstack-oss
This commit is contained in:
commit
4e544ce0f9
@ -113,29 +113,29 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe
|
||||
String certificate = cmd.getCertificate();
|
||||
|
||||
//write the cert to /etc/cloud/consoleproxy/cert/
|
||||
String strDirectoy ="/etc/cloud/consoleproxy/cert/";
|
||||
boolean dirCreated = (new File(strDirectoy)).mkdir();
|
||||
if (dirCreated) {
|
||||
s_logger.info("Directory: " + strDirectoy + " created");
|
||||
|
||||
//copy cert to the dir
|
||||
try {
|
||||
boolean dirCreated = false;
|
||||
String strDirectoy = "/etc/cloud/consoleproxy/cert/";
|
||||
dirCreated = (new File(strDirectoy)).mkdirs();
|
||||
|
||||
if (dirCreated)
|
||||
{
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.info("Directory: " + strDirectoy + " created");
|
||||
//copy cert to the dir
|
||||
FileWriter fstream = new FileWriter("/etc/cloud/consoleproxy/cert/customcert");
|
||||
BufferedWriter out = new BufferedWriter(fstream);
|
||||
out.write(certificate);
|
||||
//Close the output stream
|
||||
out.close();
|
||||
}catch (Exception e){
|
||||
s_logger.warn("Unable to write file to /etc/cloud/consoleproxy/cert/ on console proxy", e);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
success = true;
|
||||
return new Answer(cmd, success, "Cert string in the console proxy resource status:");
|
||||
return new Answer(cmd, success, "Custom certificate update required status");
|
||||
}catch (Exception e)
|
||||
{
|
||||
s_logger.error("Unable to read the cert string in console proxy resource");
|
||||
s_logger.error("Unable to read the cert string in console proxy resource",e);
|
||||
success = false;
|
||||
}
|
||||
return new Answer(cmd, success, "Cert string in the console proxy resource status:");
|
||||
return new Answer(cmd, success, "Custom certificate response from the updatecertificate flow");
|
||||
}
|
||||
|
||||
protected Answer execute(final CheckConsoleProxyLoadCommand cmd) {
|
||||
|
||||
@ -207,6 +207,13 @@
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="package-tools" depends="-init-package">
|
||||
<delete file="${publish.dir}/cloudapitools.zip" />
|
||||
<zip destfile="${publish.dir}/cloudapitools.zip" compress="false">
|
||||
<zipfileset dir="${tools.dist.dir}" filemode="555" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="clean-packages">
|
||||
<delete>
|
||||
<fileset dir="${dist.dir}" includes="*.zip" />
|
||||
|
||||
@ -135,7 +135,9 @@ public interface HostDao extends GenericDao<HostVO, Long> {
|
||||
|
||||
long getNextSequence(long hostId);
|
||||
|
||||
void loadDetails(HostVO host);
|
||||
void loadDetails(HostVO host);
|
||||
|
||||
HostVO findConsoleProxyHost(String name, Type type);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
||||
protected final SearchBuilder<HostVO> UnmanagedDirectConnectSearch;
|
||||
protected final SearchBuilder<HostVO> MaintenanceCountSearch;
|
||||
protected final SearchBuilder<HostVO> ClusterSearch;
|
||||
protected final SearchBuilder<HostVO> ConsoleProxyHostSearch;
|
||||
|
||||
protected final Attribute _statusAttr;
|
||||
protected final Attribute _msIdAttr;
|
||||
@ -154,6 +155,11 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
||||
ClusterSearch = createSearchBuilder();
|
||||
ClusterSearch.and("cluster", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
|
||||
ClusterSearch.done();
|
||||
|
||||
ConsoleProxyHostSearch = createSearchBuilder();
|
||||
ConsoleProxyHostSearch.and("name", ConsoleProxyHostSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
ConsoleProxyHostSearch.and("type", ConsoleProxyHostSearch.entity().getType(), SearchCriteria.Op.EQ);
|
||||
ConsoleProxyHostSearch.done();
|
||||
|
||||
PodSearch = createSearchBuilder();
|
||||
PodSearch.and("pod", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
@ -442,7 +448,20 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
||||
SearchCriteria<HostVO> sc = DcSearch.create("dc", dcId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HostVO findConsoleProxyHost(String name, Type type) {
|
||||
SearchCriteria<HostVO> sc = ConsoleProxyHostSearch.create();
|
||||
sc.setParameters("name", name);
|
||||
sc.setParameters("type", type);
|
||||
List<HostVO>hostList = listBy(sc);
|
||||
|
||||
if(hostList==null || hostList.size() == 0)
|
||||
return null;
|
||||
else
|
||||
return hostList.get(0);
|
||||
}
|
||||
|
||||
public List<HostVO> listByHostPod(long podId) {
|
||||
SearchCriteria<HostVO> sc = PodSearch.create("pod", podId);
|
||||
return listBy(sc);
|
||||
|
||||
@ -36,6 +36,7 @@ import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.network.DomainRouterService;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.security.NetworkGroupManager;
|
||||
@ -154,6 +155,8 @@ public class ApiDispatcher {
|
||||
throw new ServerApiException(BaseCmd.PARAM_ERROR, cause.getMessage());
|
||||
} else if (cause instanceof PermissionDeniedException) {
|
||||
throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, cause.getMessage());
|
||||
} else if (cause instanceof ResourceAllocationException){
|
||||
throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, cause.getMessage());
|
||||
}
|
||||
s_logger.warn("Exception executing method " + methodName + " for command " + cmd.getClass().getSimpleName(), ite);
|
||||
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to execute method " + methodName + " for command " + cmd.getClass().getSimpleName() + ", internal error in the implementation.");
|
||||
|
||||
@ -19,13 +19,15 @@ package com.cloud.api.commands;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.BaseCmd;
|
||||
import com.cloud.api.BaseAsyncCmd;
|
||||
import com.cloud.api.Implementation;
|
||||
import com.cloud.api.Parameter;
|
||||
import com.cloud.api.response.StatusResponse;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@Implementation(method="uploadCertificate")
|
||||
public class UploadCustomCertificateCmd extends BaseCmd {
|
||||
public class UploadCustomCertificateCmd extends BaseAsyncCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(UploadCustomCertificateCmd.class.getName());
|
||||
|
||||
private static final String s_name = "uploadcustomcertificateresponse";
|
||||
@ -37,11 +39,7 @@ public class UploadCustomCertificateCmd extends BaseCmd {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public StatusResponse getResponse() {
|
||||
Boolean status = (Boolean)getResponseObject();
|
||||
@ -51,4 +49,29 @@ public class UploadCustomCertificateCmd extends BaseCmd {
|
||||
response.setResponseName(getName());
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_VOLUME_CREATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return ("Uploading custom certificate to the db, and applying it to the cpvm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public static String getResultObjectName() {
|
||||
return "volume";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -236,14 +236,11 @@ public class ApiXmlDocReader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
out.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +129,6 @@ public class ApiXmlDocWriter {
|
||||
// //Get fields from superclass
|
||||
Class<?> superClass = clas.getSuperclass();
|
||||
String superName = superClass.getName();
|
||||
// while (BaseCmd.class.isAssignableFrom(superClass) && !superClass.getName().equals(BaseCmd.class.getName())) {
|
||||
if (!superName.equals(BaseCmd.class.getName()) && !superName.equals(BaseAsyncCmd.class.getName()) && !superName.equals(BaseAsyncCreateCmd.class.getName())) {
|
||||
Field[] superClassFields = superClass.getDeclaredFields();
|
||||
if (superClassFields != null) {
|
||||
@ -140,8 +139,6 @@ public class ApiXmlDocWriter {
|
||||
}
|
||||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
for (Field f : fields) {
|
||||
Parameter parameterAnnotation = f.getAnnotation(Parameter.class);
|
||||
|
||||
@ -34,6 +34,7 @@ import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
|
||||
import com.cloud.agent.api.GetVncPortAnswer;
|
||||
import com.cloud.agent.api.GetVncPortCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.agent.api.StopCommand;
|
||||
import com.cloud.api.ServerApiException;
|
||||
import com.cloud.api.commands.DestroyConsoleProxyCmd;
|
||||
@ -54,9 +55,10 @@ import com.cloud.utils.component.Inject;
|
||||
import com.cloud.vm.ConsoleProxyVO;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VirtualMachineName;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.dao.ConsoleProxyDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@ -74,13 +76,13 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
|
||||
@Inject
|
||||
private VMInstanceDao _instanceDao;
|
||||
private ConsoleProxyListener _listener;
|
||||
|
||||
protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT;
|
||||
protected int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT;
|
||||
protected boolean _sslEnabled = false;
|
||||
@Inject
|
||||
AgentManager _agentMgr;
|
||||
|
||||
@Inject
|
||||
protected ConsoleProxyDao _cpDao;
|
||||
public int getVncPort(VMInstanceVO vm) {
|
||||
if (vm.getHostId() == null) {
|
||||
return -1;
|
||||
@ -324,5 +326,11 @@ public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, Virtu
|
||||
@Override
|
||||
public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyCustomCertToNewProxy(StartupProxyCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import com.cloud.agent.api.AgentControlAnswer;
|
||||
import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
|
||||
import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
|
||||
@ -16,4 +17,5 @@ public interface AgentHook {
|
||||
void onAgentConnect(HostVO host, StartupCommand cmd);
|
||||
|
||||
public void onAgentDisconnect(long agentId, Status state);
|
||||
boolean applyCustomCertToNewProxy(StartupProxyCommand cmd);
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
|
||||
import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
|
||||
@ -66,6 +67,10 @@ public class ConsoleProxyListener implements Listener {
|
||||
@Override
|
||||
public void processConnect(HostVO host, StartupCommand cmd) {
|
||||
_proxyMgr.onAgentConnect(host, cmd);
|
||||
|
||||
if (cmd instanceof StartupProxyCommand) {
|
||||
_proxyMgr.applyCustomCertToNewProxy((StartupProxyCommand)cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -56,9 +56,11 @@ import com.cloud.agent.api.Start2Command;
|
||||
import com.cloud.agent.api.StartConsoleProxyAnswer;
|
||||
import com.cloud.agent.api.StartConsoleProxyCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.StopCommand;
|
||||
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
||||
import com.cloud.agent.api.proxy.UpdateCertificateCommand;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO.SshMonitor;
|
||||
@ -70,13 +72,15 @@ import com.cloud.async.AsyncJobExecutor;
|
||||
import com.cloud.async.AsyncJobManager;
|
||||
import com.cloud.async.AsyncJobVO;
|
||||
import com.cloud.async.BaseAsyncJobExecutor;
|
||||
import com.cloud.certificate.CertificateVO;
|
||||
import com.cloud.certificate.dao.CertificateDao;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.dc.dao.VlanDao;
|
||||
@ -97,8 +101,8 @@ import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.ha.HighAvailabilityManager;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.info.ConsoleProxyConnectionInfo;
|
||||
import com.cloud.info.ConsoleProxyInfo;
|
||||
@ -109,10 +113,10 @@ import com.cloud.info.RunningHostInfoAgregator;
|
||||
import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo;
|
||||
import com.cloud.maid.StackMaid;
|
||||
import com.cloud.network.IpAddrAllocator;
|
||||
import com.cloud.network.IpAddrAllocator.networkInfo;
|
||||
import com.cloud.network.Network.TrafficType;
|
||||
import com.cloud.network.NetworkConfigurationVO;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.IpAddrAllocator.networkInfo;
|
||||
import com.cloud.network.Network.TrafficType;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
@ -124,9 +128,9 @@ import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePoolVO;
|
||||
import com.cloud.storage.VMTemplateHostVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateHostDao;
|
||||
@ -155,12 +159,12 @@ import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.State;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.Event;
|
||||
import com.cloud.vm.VirtualMachineGuru;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VirtualMachineName;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.VmManager;
|
||||
import com.cloud.vm.VirtualMachine.Event;
|
||||
import com.cloud.vm.dao.ConsoleProxyDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.google.gson.Gson;
|
||||
@ -229,12 +233,12 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
private HostDao _hostDao;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
@Inject
|
||||
private CertificateDao _certDao;
|
||||
@Inject
|
||||
private VMInstanceDao _instanceDao;
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
|
||||
@Inject private VMTemplateHostDao _vmTemplateHostDao;
|
||||
@Inject private AgentManager _agentMgr;
|
||||
@Inject private StorageManager _storageMgr;
|
||||
@ -2432,4 +2436,57 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
public boolean processDeploymentResult(Commands cmds, ConsoleProxyVO proxy, VirtualMachineProfile profile, DeployDestination dest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyCustomCertToNewProxy(StartupProxyCommand cmd){
|
||||
//this is the case for updating cust cert on each new starting proxy, if such cert exists
|
||||
//get cert from db
|
||||
List<CertificateVO> certList = _certDao.listAll();
|
||||
|
||||
if(certList.size()>0){
|
||||
CertificateVO cert = certList.get(0);//there will only be 1 cert in db for now
|
||||
String certStr = cert.getCertificate();
|
||||
long proxyVmId = ((StartupProxyCommand)cmd).getProxyVmId();
|
||||
ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId);
|
||||
//find corresponding host
|
||||
if(consoleProxy!=null){
|
||||
HostVO consoleProxyHost = _hostDao.findConsoleProxyHost(consoleProxy.getName(), Type.ConsoleProxy);
|
||||
//now send a command to console proxy
|
||||
UpdateCertificateCommand certCmd = new UpdateCertificateCommand(certStr);
|
||||
try {
|
||||
Answer updateCertAns = _agentMgr.send(consoleProxyHost.getId(), certCmd);
|
||||
if(updateCertAns.getResult() == true)
|
||||
{
|
||||
//we have the cert copied over on cpvm
|
||||
long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "rebooting console proxy with Id: "+consoleProxy.getId());
|
||||
rebootProxy(consoleProxy.getId(), eventId);
|
||||
//when cp reboots, the context will be reinit with the new cert
|
||||
s_logger.info("Successfully rebooted console proxy resource after custom certificate application");
|
||||
return true;
|
||||
}
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource", e);
|
||||
return false;
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return false;//no cert
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Long saveScheduledEvent(Long userId, Long accountId, String type, String description)
|
||||
{
|
||||
EventVO event = new EventVO();
|
||||
event.setUserId(userId);
|
||||
event.setAccountId(accountId);
|
||||
event.setType(type);
|
||||
event.setState(EventState.Scheduled);
|
||||
event.setDescription("Scheduled async job for "+description);
|
||||
event = _eventDao.persist(event);
|
||||
return event.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1219,5 +1219,5 @@ public interface ManagementServer {
|
||||
*/
|
||||
String[] getHypervisors(ListHypervisorsCmd cmd);
|
||||
|
||||
boolean uploadCertificate(UploadCustomCertificateCmd cmd);
|
||||
boolean uploadCertificate(UploadCustomCertificateCmd cmd) throws ResourceAllocationException;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import java.net.URLEncoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@ -148,6 +149,7 @@ import com.cloud.async.dao.AsyncJobDao;
|
||||
import com.cloud.async.executor.ExtractJobResultObject;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.certificate.CertificateVO;
|
||||
import com.cloud.certificate.dao.CertificateDao;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
@ -174,6 +176,7 @@ import com.cloud.dc.dao.PodVlanMapDao;
|
||||
import com.cloud.dc.dao.VlanDao;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.EventState;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.EventUtils;
|
||||
import com.cloud.event.EventVO;
|
||||
@ -6931,41 +6934,64 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private Long saveScheduledEvent(Long userId, Long accountId, String type, String description)
|
||||
{
|
||||
EventVO event = new EventVO();
|
||||
event.setUserId(userId);
|
||||
event.setAccountId(accountId);
|
||||
event.setType(type);
|
||||
event.setState(EventState.Scheduled);
|
||||
event.setDescription("Scheduled async job for "+description);
|
||||
event = _eventDao.persist(event);
|
||||
return event.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean uploadCertificate(UploadCustomCertificateCmd cmd) {
|
||||
public boolean uploadCertificate(UploadCustomCertificateCmd cmd) throws ResourceAllocationException {
|
||||
//limit no.of certs uploaded to 1
|
||||
if(_certDao.listAll().size()>0){
|
||||
throw new ResourceAllocationException("There is already a custom certificate in the db");
|
||||
}
|
||||
|
||||
String certificatePath = cmd.getPath();
|
||||
Long certVOId = _certDao.persistCustomCertToDb(certificatePath);//0 implies failure
|
||||
|
||||
if (certVOId!=null && certVOId!=0) {
|
||||
//certficate uploaded to db successfully
|
||||
if (certVOId!=null && certVOId!=0)
|
||||
{
|
||||
//certficate uploaded to db successfully
|
||||
//get a list of all Console proxies from the cp table
|
||||
List<ConsoleProxyVO> cpList = _consoleProxyDao.listAll();
|
||||
|
||||
//get a list of all hosts from host table
|
||||
List<HostVO> hosts = _hostDao.listAll();
|
||||
|
||||
List<HostVO> consoleProxyList = new ArrayList<HostVO>();
|
||||
|
||||
//find the console proxies, and send the command to them
|
||||
for(HostVO host : hosts) {
|
||||
if(host.getType().equals(com.cloud.host.Host.Type.ConsoleProxy)){
|
||||
consoleProxyList.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
for(HostVO consoleProxy : consoleProxyList){
|
||||
for(ConsoleProxyVO cp : cpList)
|
||||
{
|
||||
HostVO cpHost = _hostDao.findConsoleProxyHost(cp.getName(), com.cloud.host.Host.Type.ConsoleProxy);
|
||||
|
||||
//now send a command to each console proxy
|
||||
UpdateCertificateCommand certCmd = new UpdateCertificateCommand(_certDao.findById(certVOId).getCertificate());
|
||||
try {
|
||||
Answer updateCertAns = _agentMgr.send(consoleProxy.getId(), certCmd);
|
||||
Answer updateCertAns = _agentMgr.send(cpHost.getId(), certCmd);
|
||||
if(updateCertAns.getResult() == true)
|
||||
{
|
||||
//we have the cert copied over on cpvm
|
||||
long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "rebooting console proxy with Id: "+cp.getId());
|
||||
_consoleProxyMgr.rebootProxy(cp.getId(), eventId);
|
||||
//when cp reboots, the context will be reinit with the new cert
|
||||
}
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Unable to send command to the console proxy resource", e);
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource", e);
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Unable to send command to the console proxy resource", e);
|
||||
s_logger.warn("Unable to send update certificate command to the console proxy resource", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2487,9 +2487,12 @@ public class StorageManagerImpl implements StorageManager {
|
||||
|
||||
|
||||
// Check that the volume is stored on shared storage
|
||||
if (!volumeOnSharedStoragePool(volume)) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
|
||||
}
|
||||
// NOTE: We used to ensure the volume is on shared storage before deleting. However, this seems like an unnecessary check since all we allow
|
||||
// is deleting a detached volume. Is there a technical reason why the volume has to be on shared storage? If so, uncomment this...otherwise,
|
||||
// just delete the detached volume regardless of storage pool.
|
||||
// if (!volumeOnSharedStoragePool(volume)) {
|
||||
// throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
|
||||
// }
|
||||
|
||||
// Check that the volume is not currently attached to any VM
|
||||
if (volume.getInstanceId() != null) {
|
||||
|
||||
@ -2006,6 +2006,7 @@ a:hover.search_button {
|
||||
height:auto;
|
||||
float:left;
|
||||
text-align:left;
|
||||
background:#FFF url(../images/midmenu_hover.gif) repeat-x top left;
|
||||
color:#CCC;
|
||||
font-size:11px;
|
||||
font-weight:normal;
|
||||
@ -2251,6 +2252,25 @@ a:hover.search_button {
|
||||
color:#999;
|
||||
}
|
||||
|
||||
.midmenu_emptymsgbox {
|
||||
width:220px;
|
||||
height:auto;
|
||||
float:left;
|
||||
background:#d4d4d4 url(../images/midmenu_emptymsg.gif) repeat-x top left;
|
||||
margin:0 0 0 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.midmenu_emptymsgbox p{
|
||||
width:200px;
|
||||
height:auto;
|
||||
float:left;
|
||||
color:#666;
|
||||
font-size:11px;
|
||||
font-weight:normal;
|
||||
margin:0 0 0 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.main_contentarea_with_midmenu {
|
||||
width:auto;
|
||||
@ -2448,6 +2468,30 @@ a:hover.search_button {
|
||||
color:#333;
|
||||
font-size:11px;
|
||||
}
|
||||
.grid_row_cell .error_text {
|
||||
width:92%;
|
||||
height:16px;
|
||||
float:left;
|
||||
margin:0 0 0 10px;
|
||||
display:inline;
|
||||
padding:0 0 0 2px;
|
||||
border:1px solid #999;
|
||||
background:#ffe5e5;
|
||||
color:#333;
|
||||
font-size:11px;
|
||||
}
|
||||
|
||||
.errormsg {
|
||||
width:80%;
|
||||
height:auto;
|
||||
float:left;
|
||||
margin:3px 0 0 10px;
|
||||
display:inline;
|
||||
padding:0 0 0 2px;
|
||||
color:#a90000;
|
||||
font-size:11px;
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
.grid_row_cell .select {
|
||||
width:92%;
|
||||
@ -3043,7 +3087,7 @@ a:hover.search_button {
|
||||
height:auto;
|
||||
float:left;
|
||||
position:absolute;
|
||||
background:#FFF url(../images/midmenu_hover.gif) repeat top left;
|
||||
background:#FFF repeat top left;
|
||||
border:1px solid #CCC;
|
||||
top:18px;
|
||||
right:1px;
|
||||
|
||||
BIN
ui/new/images/midmenu_emptymsg.gif
Normal file
BIN
ui/new/images/midmenu_emptymsg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 215 B |
@ -316,7 +316,7 @@ long milliseconds = new Date().getTime();
|
||||
<!-- Mid Menu starts here-->
|
||||
<div class="midmenu_panel" id="middle_menu">
|
||||
<div class="midmenu_box" id="midmenu_container">
|
||||
|
||||
<div class="midmenu_emptymsgbox"><p>No Items Available</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mid Menu ends here-->
|
||||
|
||||
@ -166,15 +166,15 @@
|
||||
</div>
|
||||
<div class="grid_rows even" id="create_port_forwarding_row">
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<input id="public_port" class="text" style="width: 90%;" type="text" />
|
||||
<input id="public_port" class="text" style="width: 70%;" type="text" />
|
||||
<div id="public_port_errormsg" class="errormsg" style="display: none;">Error msg will appear here</div>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<input id="private_port" class="text" style="width: 90%;" type="text" />
|
||||
<input id="private_port" class="text" style="width: 70%;" type="text" />
|
||||
<div id="private_port_errormsg" class="errormsg" style="display: none;">Error msg will appear here</div>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<select class="select" id="protocol">
|
||||
<select class="select" id="protocol" style="width:70%;">
|
||||
<option value="TCP">TCP</option>
|
||||
<option value="UDP">UDP</option>
|
||||
</select>
|
||||
@ -220,19 +220,19 @@
|
||||
</div>
|
||||
<div class="grid_rows even" id="create_load_balancer_row">
|
||||
<div class="grid_row_cell" style="width: 25%;">
|
||||
<input id="name" class="text" style="width: 90%;" type="text" />
|
||||
<input id="name" class="text" style="width: 70%;" type="text" />
|
||||
<div id="name_errormsg" class="errormsg" style="display: none;">Error msg will appear here</div>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<input id="public_port" class="text" style="width: 90%;" type="text" />
|
||||
<input id="public_port" class="text" style="width: 70%;" type="text" />
|
||||
<div id="public_port_errormsg" class="errormsg" style="display: none;">Error msg will appear here</div>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<input id="private_port" class="text" style="width: 90%;" type="text" />
|
||||
<input id="private_port" class="text" style="width: 70%;" type="text" />
|
||||
<div id="private_port_errormsg" class="errormsg" style="display: none;">Error msg will appear here</div>
|
||||
</div>
|
||||
<div class="grid_row_cell" style="width: 15%;">
|
||||
<select id="algorithm_select" class="select" style="width: 90%;">
|
||||
<select id="algorithm_select" class="select" style="width: 70%;">
|
||||
<option value="roundrobin">roundrobin</option>
|
||||
<option value="leastconn">leastconn</option>
|
||||
<option value="source">source</option>
|
||||
|
||||
@ -191,8 +191,7 @@ function clusterJSONToTreeNode(json, $clusterNode) {
|
||||
}
|
||||
|
||||
//$menuItem1 is either $leftmenuItem1 or $midmenuItem1
|
||||
function showPage($pageToShow, $menuItem1) {
|
||||
clearMiddleMenu();
|
||||
function showPage($pageToShow, $menuItem1) {
|
||||
if($pageToShow.length == 0) { //resource.jsp is not loaded in right panel
|
||||
$("#right_panel").load("jsp/resource.jsp", function(){
|
||||
showPage2($($pageToShow.selector), $menuItem1); //$pageToShow is still empty (i.e. $pageToShow.length == 0), So, select the element again.
|
||||
@ -223,11 +222,16 @@ function showPage2($pageToShow, $menuItem1) {
|
||||
$pageToShow.data("jsonObj", jsonObj);
|
||||
}
|
||||
|
||||
if($pageToShow.attr("id") == "resource_page") {
|
||||
if($pageToShow.attr("id") == "resource_page") {
|
||||
clearMiddleMenu();
|
||||
hideMiddleMenu();
|
||||
|
||||
initAddZoneButton($("#midmenu_add_link"));
|
||||
initDialog("dialog_add_zone");
|
||||
}
|
||||
else if($pageToShow.attr("id") == "zone_page") {
|
||||
else if($pageToShow.attr("id") == "zone_page") {
|
||||
hideMiddleMenu();
|
||||
|
||||
initAddPodButton($("#midmenu_add_link"));
|
||||
initAddVLANButton($("#midmenu_add2_link"));
|
||||
initAddSecondaryStorageButton($("#midmenu_add3_link"));
|
||||
@ -249,11 +253,12 @@ function showPage2($pageToShow, $menuItem1) {
|
||||
//var afterSwitchFnArray = [afterSwitchToDetailsTab, afterSwitchToNetworkTab, afterSwitchToSecondaryStorageTab];
|
||||
switchBetweenDifferentTabs(tabArray, tabContentArray);
|
||||
$zonePage.find("#tab_details").click();
|
||||
|
||||
hideMiddleMenu();
|
||||
|
||||
zoneJsonToRightPanel($menuItem1);
|
||||
}
|
||||
else if($pageToShow.attr("id") == "pod_page") {
|
||||
else if($pageToShow.attr("id") == "pod_page") {
|
||||
hideMiddleMenu();
|
||||
|
||||
initAddHostButton($("#midmenu_add_link"));
|
||||
initAddPrimaryStorageButton($("#midmenu_add2_link"));
|
||||
|
||||
@ -264,21 +269,22 @@ function showPage2($pageToShow, $menuItem1) {
|
||||
if (getHypervisorType() == 'kvm')
|
||||
$("#dialog_add_pool").find("#add_pool_protocol").empty().html('<option value="nfs">NFS</option>');
|
||||
bindEventHandlerToDialogAddPool();
|
||||
|
||||
showMiddleMenu();
|
||||
|
||||
podJsonToRightPanel($menuItem1);
|
||||
|
||||
var podId = jsonObj.id;
|
||||
$("#midmenu_container").empty();
|
||||
listMidMenuItems2(("listHosts&type=Routing&podid="+podId), "listhostsresponse", "host", hostToMidmenu, hostToRightPanel, hostGetMidmenuId, false, false);
|
||||
listMidMenuItems2(("listStoragePools&podid="+podId), "liststoragepoolsresponse", "storagepool", primarystorageToMidmenu, primarystorageToRightPanel, primarystorageGetMidmenuId, false, false);
|
||||
//var podId = jsonObj.id;
|
||||
//$("#midmenu_container").empty();
|
||||
//listMidMenuItems2(("listHosts&type=Routing&podid="+podId), "listhostsresponse", "host", hostToMidmenu, hostToRightPanel, hostGetMidmenuId, false, false);
|
||||
//listMidMenuItems2(("listStoragePools&podid="+podId), "liststoragepoolsresponse", "storagepool", primarystorageToMidmenu, primarystorageToRightPanel, primarystorageGetMidmenuId, false, false);
|
||||
}
|
||||
else if($pageToShow.attr("id") == "cluster_page") {
|
||||
clearMiddleMenu();
|
||||
showMiddleMenu();
|
||||
|
||||
$("#midmenu_add_link").unbind("click").hide();
|
||||
$("#midmenu_add2_link").unbind("click").hide();
|
||||
$("#midmenu_add3_link").unbind("click").hide();
|
||||
|
||||
showMiddleMenu();
|
||||
$("#midmenu_add3_link").unbind("click").hide();
|
||||
|
||||
clusterJsonToRightPanel($menuItem1);
|
||||
|
||||
var clusterId = jsonObj.id;
|
||||
@ -1274,9 +1280,10 @@ function initAddHostButton($midmenuAddLink1) {
|
||||
|
||||
var password = trim($thisDialog.find("#host_password").val());
|
||||
array1.push("&password="+encodeURIComponent(password));
|
||||
|
||||
|
||||
var newClusterName;
|
||||
if(clusterRadio == "new_cluster_radio") {
|
||||
var newClusterName = trim($thisDialog.find("#new_cluster_name").val());
|
||||
newClusterName = trim($thisDialog.find("#new_cluster_name").val());
|
||||
array1.push("&clustername="+todb(newClusterName));
|
||||
}
|
||||
else if(clusterRadio == "existing_cluster_radio") {
|
||||
@ -1304,6 +1311,7 @@ function initAddHostButton($midmenuAddLink1) {
|
||||
$thisDialog.find("#spinning_wheel").hide();
|
||||
$thisDialog.dialog("close");
|
||||
|
||||
showMiddleMenu();
|
||||
var $midmenuItem1 = $("#midmenu_item").clone();
|
||||
$("#midmenu_container").append($midmenuItem1.fadeIn("slow"));
|
||||
var items = json.addhostresponse.host;
|
||||
@ -1319,13 +1327,16 @@ function initAddHostButton($midmenuAddLink1) {
|
||||
}
|
||||
}
|
||||
|
||||
if(clusterRadio == "new_cluster_radio")
|
||||
$thisDialog.find("#new_cluster_name").val("");
|
||||
|
||||
refreshClusterUnderPod($("#pod_" + podObj.id));
|
||||
if(clusterRadio == "new_cluster_radio") {
|
||||
refreshClusterUnderPod($("#pod_" + podObj.id), newClusterName);
|
||||
$thisDialog.find("#new_cluster_name").val("");
|
||||
}
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
refreshClusterUnderPod($("#pod_" + podObj.id));
|
||||
if(clusterRadio == "new_cluster_radio") {
|
||||
refreshClusterUnderPod($("#pod_" + podObj.id), newClusterName);
|
||||
$thisDialog.find("#new_cluster_name").val(""); //even AddHost fails, new cluster is still created. So, we clean up new cluster field to avoid the same one gets created twice.
|
||||
}
|
||||
handleErrorInDialog(XMLHttpResponse, $thisDialog);
|
||||
}
|
||||
});
|
||||
@ -1338,7 +1349,7 @@ function initAddHostButton($midmenuAddLink1) {
|
||||
});
|
||||
}
|
||||
|
||||
function refreshClusterUnderPod($podNode) {
|
||||
function refreshClusterUnderPod($podNode, newClusterName) {
|
||||
var podId = $podNode.data("podId");
|
||||
$.ajax({
|
||||
data: createURL("command=listClusters&podid="+podId+maxPageSize),
|
||||
@ -1349,9 +1360,14 @@ function refreshClusterUnderPod($podNode) {
|
||||
var container = $podNode.find("#clusters_container").empty();
|
||||
if (items != null && items.length > 0) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var clusterTemplate = $("#leftmenu_cluster_node_template").clone(true);
|
||||
clusterJSONToTreeNode(items[i], clusterTemplate);
|
||||
container.append(clusterTemplate.show());
|
||||
var $clusterNode = $("#leftmenu_cluster_node_template").clone(true);
|
||||
var item = items[i];
|
||||
clusterJSONToTreeNode(item, $clusterNode);
|
||||
container.append($clusterNode.show());
|
||||
|
||||
if(newClusterName != null && fromdb(item.name) == newClusterName) {
|
||||
$clusterNode.find("#cluster_name").click();
|
||||
}
|
||||
}
|
||||
$podNode.find("#pod_arrow").removeClass("white_nonexpanded_close").addClass("expanded_open");
|
||||
$podNode.find("#pod_content").show();
|
||||
|
||||
@ -959,7 +959,7 @@ function showStorageTab(domainId, targetTab) {
|
||||
switch (linkAction) {
|
||||
case "volume_action_delete" :
|
||||
//check if this volume is attached to a virtual machine. If yes, can't be deleted.
|
||||
if(vmname != null && (vmname != "" || vmname != "none")) {
|
||||
if(vmname != null && vmname != "" && vmname != "none") {
|
||||
$("#dialog_alert").html("<p>This volume is attached to virtual machine " + vmname + " and can't be deleted.</p>")
|
||||
$("#dialog_alert").dialog("open");
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user