protected NodeAndInitialCredentials createNodeWithGroupEncodedIntoName()

in profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java [152:372]


   protected NodeAndInitialCredentials<ServerInDataCenter> createNodeWithGroupEncodedIntoName(String group, String name, TemplateWithDataCenter template) {
      checkArgument(template.getLocation().getScope() == LocationScope.ZONE, "Template must use a ZONE-scoped location");
      final String dataCenterId = template.getDataCenter().id();
      Hardware hardware = template.getHardware();
      TemplateOptions options = template.getOptions();
      final String loginUser = isNullOrEmpty(options.getLoginUser()) ? "root" : options.getLoginUser();
      final String pubKey = options.getPublicKey();
      final String password = options.hasLoginPassword() ? options.getLoginPassword() : passwordGenerator.generate();
      final org.jclouds.compute.domain.Image image = template.getImage();
      final int[] inboundPorts = template.getOptions().getInboundPorts();

      // provision all volumes based on hardware
      List<? extends Volume> volumes = hardware.getVolumes();
      List<String> volumeIds = Lists.newArrayListWithExpectedSize(volumes.size());

      int i = 1;
      for (final Volume volume : volumes) {
         try {
            logger.trace("<< provisioning volume '%s'", volume);
            final org.apache.jclouds.profitbricks.rest.domain.Volume.Request.CreatePayload.Builder request = org.apache.jclouds.profitbricks.rest.domain.Volume.Request.creatingBuilder();
            if (i == 1) {
               request.image(image.getId());
               // we don't need to pass password to the API if we're using a snapshot
               Provisionable.Type provisionableType = Provisionable.Type.fromValue(
                       image.getUserMetadata().get(ProvisionableToImage.KEY_PROVISIONABLE_TYPE));
               if (provisionableType == Provisionable.Type.IMAGE) {
                  if (pubKey != null) {
                     request.sshKeys(new HashSet<String>(Arrays.asList(pubKey)));
                  } else {
                     request.imagePassword(password);
                  }
               }

            }
            request.dataCenterId(dataCenterId).
                    name(format("%s-disk-%d", name, i++)).
                    size(volume.getSize().intValue()).
                    type(VolumeType.HDD);

            org.apache.jclouds.profitbricks.rest.domain.Volume vol = (org.apache.jclouds.profitbricks.rest.domain.Volume) provisioningManager
                    .provision(jobFactory.create(dataCenterId, new Supplier<Object>() {
                       @Override
                       public Object get() {
                          return api.volumeApi().createVolume(request.build());
                       }
                    }));

            volumeIds.add(vol.id());
            logger.trace(">> provisioning complete for volume. returned id='%s'", vol.id());
         } catch (Exception ex) {
            if (i - 1 == 1) // if first volume (one with image) provisioning fails; stop method
            {
               throw Throwables.propagate(ex);
            }
            logger.warn(ex, ">> failed to provision volume. skipping..");
         }
      }

      String volumeBootDeviceId = Iterables.get(volumeIds, 0); // must have atleast 1
      waitVolumeUntilAvailable.apply(VolumeRef.create(dataCenterId, volumeBootDeviceId));

      // provision server
      final Server server;
      Double cores = ComputeServiceUtils.getCores(hardware);

      Server.BootVolume bootVolume = Server.BootVolume.create(volumeBootDeviceId);

      try {
         final Server.Request.CreatePayload serverRequest = Server.Request.creatingBuilder()
                 .dataCenterId(dataCenterId)
                 .name(name)
                 .bootVolume(bootVolume)
                 .cores(cores.intValue())
                 .ram(hardware.getRam())
                 .build();

         logger.trace("<< provisioning server '%s'", serverRequest);

         server = (Server) provisioningManager.provision(jobFactory.create(dataCenterId, new Supplier<Object>() {

            @Override
            public Object get() {
               return api.serverApi().createServer(serverRequest);
            }
         }));
         logger.trace(">> provisioning complete for server. returned id='%s'", server.id());

      } catch (Exception ex) {
         logger.error(ex, ">> failed to provision server. rollbacking..");
         destroyVolumes(volumeIds, dataCenterId);
         throw Throwables.propagate(ex);
      }

      waitServerUntilAvailable.apply(ServerRef.create(dataCenterId, server.id()));
      waitDcUntilAvailable.apply(dataCenterId);

      //attach bootVolume to Server
      org.apache.jclouds.profitbricks.rest.domain.Volume volume = api.serverApi().attachVolume(Server.Request.attachVolumeBuilder()
              .dataCenterId(dataCenterId)
              .serverId(server.id())
              .volumeId(bootVolume.id())
              .build());

      trackables.waitUntilRequestCompleted(volume);
      waitServerUntilAvailable.apply(ServerRef.create(dataCenterId, server.id()));
      waitDcUntilAvailable.apply(dataCenterId);

      //fetch an existing lan and creat if non was found
      Lan lan = null;

      List<Lan> lans = api.lanApi().list(dataCenterId);
      if (lans != null && !lans.isEmpty()) {
         lan = FluentIterable.from(lans).firstMatch(new Predicate<Lan>() {
            @Override
            public boolean apply(Lan input) {
               input = api.lanApi().get(dataCenterId, input.id(), new DepthOptions().depth(3));
               return input.properties().isPublic();
            }
         }).orNull();
      }
      if (lan == null) {
         logger.warn("Could not find an existing lan Creating one....");
         lan = api.lanApi().create(Lan.Request.creatingBuilder()
                 .dataCenterId(dataCenterId)
                 .isPublic(Boolean.TRUE)
                 .name("lan " + name)
                 .build());
         trackables.waitUntilRequestCompleted(lan);
      }

      //add a NIC to the server
      int lanId = DEFAULT_LAN_ID;
      if (options.getNetworks() != null) {
         try {
            String networkId = Iterables.get(options.getNetworks(), 0);
            lanId = Integer.valueOf(networkId);
         } catch (Exception ex) {
            logger.warn("no valid network id found from options. using default id='%d'", DEFAULT_LAN_ID);
         }
      }

      Nic nic = api.nicApi().create(Nic.Request.creatingBuilder()
              .dataCenterId(dataCenterId)
              .name("jclouds" + name)
              .dhcp(Boolean.TRUE)
              .lan(lanId)
              .firewallActive(inboundPorts.length > 0)
              .serverId(server.id()).
              build());

      trackables.waitUntilRequestCompleted(nic);
      waitNICUntilAvailable.apply(NicRef.create(dataCenterId, server.id(), nic.id()));
      waitDcUntilAvailable.apply(dataCenterId);
      waitServerUntilAvailable.apply(ServerRef.create(dataCenterId, server.id()));

      Map<Integer, Integer> portsRange = getPortRangesFromList(inboundPorts);

      for (Map.Entry<Integer, Integer> range : portsRange.entrySet()) {
         FirewallRule rule = api.firewallApi().create(
                 FirewallRule.Request.creatingBuilder()
                 .dataCenterId(dataCenterId)
                 .serverId(server.id())
                 .nicId(nic.id())
                 .name(server.properties().name() + " jclouds-firewall")
                 .protocol(FirewallRule.Protocol.TCP)
                 .portRangeStart(range.getKey())
                 .portRangeEnd(range.getValue())
                 .build()
         );
         trackables.waitUntilRequestCompleted(rule);

      }

      //connect the rest of volumes to server;delete if fails
      final int volumeCount = volumeIds.size();
      for (int j = 1; j < volumeCount; j++) { // skip first; already connected
         final String volumeId = volumeIds.get(j);
         try {
            logger.trace("<< connecting volume '%s' to server '%s'", volumeId, server.id());
            provisioningManager.provision(jobFactory.create(group, new Supplier<Object>() {

               @Override
               public Object get() {
                  return api.serverApi().attachVolume(
                          Server.Request.attachVolumeBuilder()
                          .dataCenterId(dataCenterId)
                          .serverId(server.id())
                          .volumeId(volumeId)
                          .build()
                  );
               }
            }));

            logger.trace(">> volume connected.");
         } catch (Exception ex) {
            try {
               // delete unconnected volume
               logger.warn(ex, ">> failed to connect volume '%s'. deleting..", volumeId);
               destroyVolume(volumeId, dataCenterId);
               logger.warn(ex, ">> rolling back server..", server.id());
               destroyServer(server.id(), dataCenterId);
               throw ex;
            } catch (Exception ex1) {
               logger.error(ex, ">> failed to rollback");
            }
         }
      }
      waitDcUntilAvailable.apply(dataCenterId);
      waitServerUntilAvailable.apply(ServerRef.create(dataCenterId, server.id()));

      LoginCredentials serverCredentials = LoginCredentials.builder()
              .user(loginUser)
              .privateKey(pubKey)
              .password(password)
              .build();

      String serverInDataCenterId = DataCenterAndId.fromDataCenterAndId(dataCenterId, server.id()).slashEncode();
      ServerInDataCenter serverInDatacenter = getNode(serverInDataCenterId);

      return new NodeAndInitialCredentials<ServerInDataCenter>(serverInDatacenter, serverInDataCenterId, serverCredentials);
   }