-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New MAAS (Metal as a Service) infrastructure. #53
base: master
Are you sure you want to change the base?
Changes from 16 commits
d91d096
89f5557
4aa46f8
b930606
cf8eea2
99efb34
8a2eed3
1669656
9840fed
3d272cf
b0b15c2
1389304
802de6f
370ec8c
416b527
c5354e5
7028dca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
#Tue Jul 18 12:01:20 CEST 2017 | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/* | ||
* ProActive Parallel Suite(TM): | ||
* The Open Source library for parallel and distributed | ||
* Workflows & Scheduling, Orchestration, Cloud Automation | ||
* and Big Data Analysis on Enterprise Grids & Clouds. | ||
* | ||
* Copyright (c) 2007 - 2017 ActiveEon | ||
* Contact: [email protected] | ||
* | ||
* This library is free software: you can redistribute it and/or | ||
* modify it under the terms of the GNU Affero General Public License | ||
* as published by the Free Software Foundation: version 3 of | ||
* the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
* If needed, contact us to obtain a release under GPL Version 2 or 3 | ||
* or a different license than the AGPL. | ||
*/ | ||
package org.ow2.proactive.connector.iaas.cloud.provider.maas; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.Future; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
import javax.ws.rs.NotSupportedException; | ||
|
||
import org.apache.log4j.Logger; | ||
import org.ow2.proactive.connector.iaas.cloud.TagManager; | ||
import org.ow2.proactive.connector.iaas.cloud.provider.CloudProvider; | ||
import org.ow2.proactive.connector.iaas.model.Hardware; | ||
import org.ow2.proactive.connector.iaas.model.Image; | ||
import org.ow2.proactive.connector.iaas.model.Infrastructure; | ||
import org.ow2.proactive.connector.iaas.model.Instance; | ||
import org.ow2.proactive.connector.iaas.model.InstanceScript; | ||
import org.ow2.proactive.connector.iaas.model.Network; | ||
import org.ow2.proactive.connector.iaas.model.ScriptResult; | ||
import org.ow2.proactive.connector.iaas.model.Tag; | ||
import org.ow2.proactive.connector.maas.MaasClient; | ||
import org.ow2.proactive.connector.maas.data.CommissioningScript; | ||
import org.ow2.proactive.connector.maas.data.Machine; | ||
import org.ow2.proactive.connector.maas.polling.MaasClientPollingService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
|
||
import com.google.common.collect.Lists; | ||
|
||
import lombok.Getter; | ||
|
||
|
||
/** | ||
* @author Vicent Kherbache | ||
* @since 09/01/17 | ||
*/ | ||
@Component | ||
public class MaasProvider implements CloudProvider { | ||
|
||
private final Logger logger = Logger.getLogger(MaasProvider.class); | ||
|
||
@Getter | ||
private final String type = "maas"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
@Autowired | ||
private TagManager tagManager; | ||
|
||
@Autowired | ||
private MaasProviderClientCache maasProviderClientCache; | ||
|
||
@Override | ||
public Set<Instance> createInstance(Infrastructure infrastructure, Instance instance) { | ||
|
||
MaasClient maasClient = maasProviderClientCache.getMaasClient(infrastructure); | ||
|
||
// Retrieve and convert the list of tags | ||
List<org.ow2.proactive.connector.maas.data.Tag> tags = convertIaasTagsToMaasTags(tagManager.retrieveAllTags(instance.getOptions())); | ||
|
||
// Initialize MAAS deployment polling | ||
MaasClientPollingService maasPollingService = new MaasClientPollingService(maasClient, | ||
Integer.valueOf(instance.getNumber())); | ||
|
||
// Start deployment(s) by ID or by resources | ||
List<Future<Machine>> futureMachines; | ||
if (instance.getId() != null) { | ||
futureMachines = IntStream.rangeClosed(1, Integer.valueOf(instance.getNumber())) | ||
.mapToObj(instanceIndexStartAt1 -> maasPollingService.deployMachine(instance.getId(), | ||
instance.getInitScript() | ||
.getScripts()[0], | ||
tags)) | ||
.collect(Collectors.toList()); | ||
} else { | ||
futureMachines = IntStream.rangeClosed(1, Integer.valueOf(instance.getNumber())) | ||
.mapToObj(instanceIndexStartAt1 -> maasPollingService.deployMachine(Integer.valueOf(instance.getHardware() | ||
.getMinCores()), | ||
Integer.valueOf(instance.getHardware() | ||
.getMinRam()), | ||
instance.getInitScript() | ||
.getScripts()[0], | ||
tags)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
// Retrieve futures (blocking calls) | ||
Set<Instance> instances = futureMachines.stream().map(futureMachine -> { | ||
try { | ||
return futureMachine.get(); | ||
} catch (InterruptedException | ExecutionException e) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
e.printStackTrace(); | ||
return null; | ||
} | ||
}).map(this::getInstanceFromMachine).collect(Collectors.toSet()); | ||
|
||
// Kill polling timeout tasks | ||
maasPollingService.shutdown(); | ||
|
||
return instances; | ||
} | ||
|
||
@Override | ||
public void deleteInstance(Infrastructure infrastructure, String instanceId) { | ||
if (!maasProviderClientCache.getMaasClient(infrastructure).releaseMachineById(instanceId)) { | ||
throw new RuntimeException("ERROR when deleting MAAS instance : " + instanceId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
} | ||
|
||
@Override | ||
public Set<Instance> getAllInfrastructureInstances(Infrastructure infrastructure) { | ||
return maasProviderClientCache.getMaasClient(infrastructure) | ||
.getMachines() | ||
.stream() | ||
.map(this::getInstanceFromMachine) | ||
.collect(Collectors.toSet()); | ||
} | ||
|
||
@Override | ||
/** | ||
* For MAAS, only the key of the tag is used as it must remains unique among all created tags. | ||
* Therefore, the key need to be customized in the file 'resources/application.properties' with | ||
* a random/unique name. The value of the tag is not used. | ||
*/ | ||
public Set<Instance> getCreatedInfrastructureInstances(Infrastructure infrastructure) { | ||
return maasProviderClientCache.getMaasClient(infrastructure) | ||
.getMachinesByTag(convertIaasTagToMaasTag(tagManager.getConnectorIaasTag())) | ||
.stream() | ||
.map(this::getInstanceFromMachine) | ||
.collect(Collectors.toSet()); | ||
} | ||
|
||
@Override | ||
/** | ||
* Upload a new *decommissioning* script to MAAS region controller. | ||
*/ | ||
public List<ScriptResult> executeScriptOnInstanceId(Infrastructure infrastructure, String instanceId, | ||
InstanceScript instanceScript) { | ||
|
||
ScriptResult scriptResult = new ScriptResult(instanceId, "", ""); | ||
|
||
StringBuilder script = new StringBuilder(); | ||
script.append("#!/bin/bash\n"); | ||
for (int i = 0; i < instanceScript.getScripts().length; i++) { | ||
script.append("\n"); | ||
script.append(instanceScript.getScripts()[i]); | ||
} | ||
|
||
CommissioningScript maasScript = maasProviderClientCache.getMaasClient(infrastructure) | ||
.postCommissioningScript(script.toString().getBytes(), | ||
instanceId); | ||
|
||
if (maasScript == null) { | ||
return Lists.newArrayList(scriptResult.withError("Unable to upload script " + instanceId)); | ||
} | ||
|
||
// Unable to retrieve scripts output, returns empty results instead | ||
return IntStream.rangeClosed(1, instanceScript.getScripts().length) | ||
.mapToObj(scriptNumber -> new ScriptResult(instanceId, "", "")) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Override | ||
public List<ScriptResult> executeScriptOnInstanceTag(Infrastructure infrastructure, String instanceTag, | ||
InstanceScript instanceScript) { | ||
|
||
return executeScriptOnInstanceId(infrastructure, | ||
maasProviderClientCache.getMaasClient(infrastructure) | ||
.getMachines() | ||
.stream() | ||
.filter(machine -> machine.getHostname() | ||
.equals(instanceTag)) | ||
.findFirst() | ||
.orElseThrow(() -> new RuntimeException("ERROR machine with hostname '" + | ||
instanceTag + | ||
"' not found")) | ||
.getSystemId(), | ||
instanceScript); | ||
} | ||
|
||
@Override | ||
public Set<Image> getAllImages(Infrastructure infrastructure) { | ||
throw new NotSupportedException("Operation not supported for MAAS"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
@Override | ||
public void deleteInfrastructure(Infrastructure infrastructure) { | ||
maasProviderClientCache.removeMaasClient(infrastructure); | ||
} | ||
|
||
@Override | ||
public String addToInstancePublicIp(Infrastructure infrastructure, String instanceId, String desiredIp) { | ||
throw new NotSupportedException("Operation not supported for MAAS"); | ||
} | ||
|
||
@Override | ||
public void removeInstancePublicIp(Infrastructure infrastructure, String instanceId, String desiredIp) { | ||
throw new NotSupportedException("Operation not supported for MAAS"); | ||
} | ||
|
||
private Instance getInstanceFromMachine(Machine machine) { | ||
|
||
return Instance.builder() | ||
.id(machine.getSystemId()) | ||
.tag(machine.getHostname()) | ||
.number("1") | ||
.hardware(Hardware.builder() | ||
.minCores(machine.getCpuCount().toString()) | ||
.minRam(machine.getMemory().toString()) | ||
.type(machine.getNodeTypeName()) | ||
.build()) | ||
.network(Network.builder().publicAddresses(Lists.newArrayList(machine.getIpAddresses())).build()) | ||
.status(machine.getStatusMessage()) | ||
.build(); | ||
} | ||
|
||
private List<org.ow2.proactive.connector.maas.data.Tag> convertIaasTagsToMaasTags(List<Tag> iaasTags) { | ||
return iaasTags.stream().map(this::convertIaasTagToMaasTag).collect(Collectors.toList()); | ||
} | ||
|
||
private org.ow2.proactive.connector.maas.data.Tag convertIaasTagToMaasTag(Tag iaasTag) { | ||
return new org.ow2.proactive.connector.maas.data.Tag(null, null, iaasTag.getKey(), iaasTag.getValue(), null); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* ProActive Parallel Suite(TM): | ||
* The Open Source library for parallel and distributed | ||
* Workflows & Scheduling, Orchestration, Cloud Automation | ||
* and Big Data Analysis on Enterprise Grids & Clouds. | ||
* | ||
* Copyright (c) 2007 - 2017 ActiveEon | ||
* Contact: [email protected] | ||
* | ||
* This library is free software: you can redistribute it and/or | ||
* modify it under the terms of the GNU Affero General Public License | ||
* as published by the Free Software Foundation: version 3 of | ||
* the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
* If needed, contact us to obtain a release under GPL Version 2 or 3 | ||
* or a different license than the AGPL. | ||
*/ | ||
package org.ow2.proactive.connector.iaas.cloud.provider.maas; | ||
|
||
import org.ow2.proactive.connector.iaas.model.Infrastructure; | ||
import org.ow2.proactive.connector.maas.MaasClient; | ||
import org.springframework.remoting.RemoteConnectFailureException; | ||
import org.springframework.stereotype.Component; | ||
|
||
|
||
/** | ||
* @author ActiveEon Team | ||
* @since 12/01/17 | ||
*/ | ||
@Component | ||
public class MaasProviderClientBuilder { | ||
|
||
public MaasClient buildMaasClientFromInfrastructure(Infrastructure infrastructure) { | ||
|
||
try { | ||
return new MaasClient(infrastructure.getEndpoint(), | ||
infrastructure.getCredentials().getPassword(), | ||
infrastructure.isAllowSelfSignedSSLCertificate()); | ||
} catch (RemoteConnectFailureException e) { | ||
throw new RuntimeException("ERROR trying to create MaasClient with infrastructure : " + infrastructure, e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* ProActive Parallel Suite(TM): | ||
* The Open Source library for parallel and distributed | ||
* Workflows & Scheduling, Orchestration, Cloud Automation | ||
* and Big Data Analysis on Enterprise Grids & Clouds. | ||
* | ||
* Copyright (c) 2007 - 2017 ActiveEon | ||
* Contact: [email protected] | ||
* | ||
* This library is free software: you can redistribute it and/or | ||
* modify it under the terms of the GNU Affero General Public License | ||
* as published by the Free Software Foundation: version 3 of | ||
* the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
* If needed, contact us to obtain a release under GPL Version 2 or 3 | ||
* or a different license than the AGPL. | ||
*/ | ||
package org.ow2.proactive.connector.iaas.cloud.provider.maas; | ||
|
||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.function.Function; | ||
|
||
import org.ow2.proactive.connector.iaas.model.Infrastructure; | ||
import org.ow2.proactive.connector.maas.MaasClient; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
|
||
|
||
/** | ||
* @author ActiveEon Team | ||
* @since 12/01/17 | ||
*/ | ||
@Component | ||
public class MaasProviderClientCache { | ||
|
||
@Autowired | ||
private MaasProviderClientBuilder maasClientBuilder; | ||
|
||
private Map<Infrastructure, MaasClient> maasClientCache; | ||
|
||
public MaasProviderClientCache() { | ||
maasClientCache = new ConcurrentHashMap<Infrastructure, MaasClient>(); | ||
} | ||
|
||
public MaasClient getMaasClient(Infrastructure infrastructure) { | ||
return buildMaasClient.apply(infrastructure); | ||
} | ||
|
||
public void removeMaasClient(Infrastructure infrastructure) { | ||
maasClientCache.remove(infrastructure); | ||
} | ||
|
||
private Function<Infrastructure, MaasClient> buildMaasClient = memoise(infrastructure -> maasClientBuilder.buildMaasClientFromInfrastructure(infrastructure)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
private Function<Infrastructure, MaasClient> memoise(Function<Infrastructure, MaasClient> fn) { | ||
return (a) -> maasClientCache.computeIfAbsent(a, fn); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the "logger" logger private static final.