JCloudsSlaveTemplate implements Describable<JCloudsSlaveTemplate>, SlaveOptions.Holder { @Restricted(NoExternalUse.class) public @Nonnull Server provisionServer(@CheckForNull ServerScope scope, @CheckForNull ProvisioningActivity.Id id) throws Openstack.ActionFailed { final String serverName = getServerName(); final SlaveOptions opts = getEffectiveSlaveOptions(); final ServerCreateBuilder builder = Builders.server(); builder.addMetadataItem(OPENSTACK_TEMPLATE_NAME_KEY, getName()); builder.addMetadataItem(OPENSTACK_CLOUD_NAME_KEY, cloud.name); if (scope == null) { scope = id == null ? new ServerScope.Node(serverName) : new ServerScope.Node(serverName, id) ; } builder.addMetadataItem(ServerScope.METADATA_KEY, scope.getValue()); LOGGER.info("Provisioning new openstack server " + serverName + " with options " + opts); builder.name(serverName); final Openstack openstack = cloud.getOpenstack(); final BootSource bootSource = opts.getBootSource(); if (bootSource == null) { LOGGER.warning("No " + BootSource.class.getSimpleName() + " set for " + getClass().getSimpleName() + " with name='" + getName() + "'."); } else { LOGGER.fine("Setting boot options to " + bootSource); bootSource.setServerBootSource(builder, openstack); } String hwid = opts.getHardwareId(); if (Util.fixEmpty(hwid) != null) { LOGGER.fine("Setting hardware Id to " + hwid); builder.flavor(hwid); } String nid = opts.getNetworkId(); if (Util.fixEmpty(nid) != null) { List<String> networks = selectNetworkIds(openstack, nid); LOGGER.fine("Setting networks to " + networks); builder.networks(networks); } String securityGroups = opts.getSecurityGroups(); if (Util.fixEmpty(securityGroups) != null) { LOGGER.fine("Setting security groups to " + securityGroups); for (String sg: parseSecurityGroups(securityGroups)) { builder.addSecurityGroup(sg); } } String kpn = opts.getKeyPairName(); if (Util.fixEmpty(kpn) != null) { LOGGER.fine("Setting keyPairName to " + kpn); builder.keypairName(kpn); } String az = opts.getAvailabilityZone(); if (Util.fixEmpty(az) != null) { LOGGER.fine("Setting availabilityZone to " + az); builder.availabilityZone(az); } @CheckForNull String userDataText = getUserData(); if (userDataText != null) { String rootUrl = Util.fixNull(Jenkins.get().getRootUrl()); UserDataVariableResolver resolver = new UserDataVariableResolver(rootUrl, serverName, labelString, opts); String content = Util.replaceMacro(userDataText, resolver); assert content != null; LOGGER.fine("Sending user-data:\n" + content); builder.userData(Base64.encode(content.getBytes(StandardCharsets.UTF_8))); } Boolean configDrive = opts.getConfigDrive(); if (configDrive != null) { builder.configDrive(configDrive); } Server server = openstack.bootAndWaitActive(builder, opts.getStartTimeout()); try { if (bootSource != null) { bootSource.afterProvisioning(server, openstack); } String poolName = opts.getFloatingIpPool(); if (poolName != null) { LOGGER.fine("Assigning floating IP from " + poolName + " to " + serverName); openstack.assignFloatingIp(server, poolName); server = openstack.updateInfo(server); LOGGER.info("Amended server: " + server.toString()); } LOGGER.info("Provisioned: " + server.toString()); return server; } catch (Throwable ex) { AsyncResourceDisposer.get().dispose(new DestroyMachine(cloud.name, server.getId())); throw ex; } } @DataBoundConstructor  JCloudsSlaveTemplate(final @Nonnull String name, final @Nonnull String labels, final @CheckForNull SlaveOptions slaveOptions); @Nonnull SlaveOptions getEffectiveSlaveOptions(); @Nonnull SlaveOptions getRawSlaveOptions(); Set<LabelAtom> getLabelSet(); @Nonnull String getName(); @Restricted(NoExternalUse.class) // Jelly + tests @Nonnull String getLabels(); boolean canProvision(final Label label); @Nonnull JCloudsSlave provisionSlave(
            @Nonnull JCloudsCloud cloud, @Nonnull ProvisioningActivity.Id id
    ); @Restricted(NoExternalUse.class) @Nonnull Server provisionServer(@CheckForNull ServerScope scope, @CheckForNull ProvisioningActivity.Id id); @Override @SuppressWarnings("unchecked") Descriptor<JCloudsSlaveTemplate> getDescriptor(); static final String OPENSTACK_CLOUD_NAME_KEY; static final String OPENSTACK_TEMPLATE_NAME_KEY; }
@Test public void noFloatingPoolId() { SlaveOptions opts = j.defaultSlaveOptions().getBuilder().floatingIpPool(null).build(); JCloudsSlaveTemplate template = j.dummySlaveTemplate(opts,"a"); JCloudsCloud cloud = j.configureSlaveProvisioningWithFloatingIP(j.dummyCloud(template)); Openstack os = cloud.getOpenstack(); template.provisionServer(null, null); verify(os).bootAndWaitActive(any(ServerCreateBuilder.class), anyInt()); verify(os, never()).assignFloatingIp(any(Server.class), any(String.class)); }
@Test public void bootFromImageVolume() { final SlaveOptions opts = dummySlaveOptions().getBuilder().bootSource(new BootSource.VolumeFromImage("src_img_id", 42)).build(); final JCloudsSlaveTemplate template = j.dummySlaveTemplate(opts, "label"); final JCloudsCloud cloud = j.configureSlaveProvisioningWithFloatingIP(j.dummyCloud(template)); final Openstack os = cloud.getOpenstack(); template.provisionServer(null, null); ArgumentCaptor<ServerCreateBuilder> captor = ArgumentCaptor.forClass(ServerCreateBuilder.class); verify(os, times(1)).bootAndWaitActive(captor.capture(), any(Integer.class)); NovaBlockDeviceMappingCreate blockDeviceMapping = getBlockDeviceMapping(captor.getValue()); assertThat(blockDeviceMapping.boot_index, equalTo(0)); assertThat(blockDeviceMapping.delete_on_termination, equalTo(true)); assertThat(blockDeviceMapping.uuid, equalTo("src_img_id")); assertThat(blockDeviceMapping.source_type, equalTo(BDMSourceType.IMAGE)); assertThat(blockDeviceMapping.destination_type, equalTo(BDMDestType.VOLUME)); assertThat(blockDeviceMapping.volume_size, equalTo(42)); }