com.vmware.appfactory.workpool.WorkpoolClientService.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.appfactory.workpool.WorkpoolClientService.java

Source

/* ***********************************************************************
 * VMware ThinApp Factory
 * Copyright (c) 2009-2013 VMware, Inc. All Rights Reserved.
 *
 * Licensed 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 com.vmware.appfactory.workpool;

import java.net.URI;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Nonnull;

import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestClientException;

import com.vmware.appfactory.common.base.AbstractRestClient;
import com.vmware.appfactory.common.exceptions.AfConflictException;
import com.vmware.appfactory.common.exceptions.AfNotFoundException;
import com.vmware.appfactory.config.ConfigRegistry;
import com.vmware.appfactory.config.ConfigRegistryConstants;
import com.vmware.thinapp.common.util.AfUtil;
import com.vmware.thinapp.common.workpool.dto.DeleteMethod;
import com.vmware.thinapp.common.workpool.dto.Lease;
import com.vmware.thinapp.common.workpool.dto.VmImage;
import com.vmware.thinapp.common.workpool.dto.Workpool;
import com.vmware.thinapp.common.workpool.exception.WpException;

/**
 * This is the main interface to the workpool service on the appliance.
 * Instead of using Workpool REST API at random locations throughout the webui,
 * they are all wrapped in methods inside this class.
 */
@Service("workpoolClient")
public class WorkpoolClientService extends AbstractRestClient {
    /**
     * Create a new instance.
     * Used to instantiate the service bean.
     */
    public WorkpoolClientService() {
        super(ConfigRegistryConstants.WORKPOOL_SERVICE_URL);
    }

    /**
     * When using the bean instance is not possible, this constructor
     * will create a new instance.
     *
     * @param config
     */
    public WorkpoolClientService(ConfigRegistry config) {
        this();
        _config = config;
    }

    /**
     * Get all known workpools.
     * @return
     * @throws WpException
     */
    public List<Workpool> getAllWorkpools() throws WpException {
        try {
            Workpool[] objects = _rest.getForObject(baseUrl() + "/workpools", Workpool[].class);

            return Arrays.asList(objects);
        } catch (RestClientException ex) {
            _log.error("Failed to load workpools from workpool service", ex);
            throw new WpException(ex);
        } catch (Exception ex) {
            _log.error("Failed to get workpools from workpool service", ex);
            throw new WpException(ex);
        }
    }

    /**
     * Returns the workpool identified by the id passed.
     *
     * @param id
     * @return
     * @throws WpException
     */
    public Workpool getWorkpoolById(Long id) throws WpException, AfNotFoundException {
        if (id == null) {
            throw new WpException("Invalid input");
        }
        try {
            return _rest.getForObject(baseUrl() + "/workpools/{id}", Workpool.class, id);
        } catch (HttpStatusCodeException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new AfNotFoundException("NOT_FOUND: " + ex.getMessage());
            }
            throw new WpException(ex);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Returns the workpool identified by the parameter name.
     *
     * @TODO Have a new API that gets workpool by name. For now, getting a list
     * and matching names.
     *
     * @param name
     * @return
     * @throws WpException
     */
    public Workpool getWorkpoolByName(String name) throws WpException, AfNotFoundException {
        // Validate input.
        if (StringUtils.isEmpty(name)) {
            throw new WpException("Invalid input");
        }
        List<Workpool> wpList = getAllWorkpools();
        if (!CollectionUtils.isEmpty(wpList)) {
            for (Workpool w : wpList)
                if (name.equals(w.getName())) {
                    return w;
                }
        }
        throw new AfNotFoundException("NOT_FOUND: " + "Workpool '" + name + " is not found");
    }

    /**
     * Deletes the workpool by id
     *
     * @param workpoolId
     * @param deleteMethod
     */
    public void deleteWorkpool(Long workpoolId, DeleteMethod deleteMethod) throws WpException {
        try {
            _rest.delete(baseUrl() + "/workpools/{workpoolId}?deleteMethod={deleteMethod}", workpoolId,
                    deleteMethod);
        } catch (RestClientException e) {
            _log.error("Cannot delete workpool id: " + workpoolId + "due to: " + e.getMessage());
            throw new WpException(e);
        }
    }

    /**
     * Acquires the lease of a workpool instance.
     *
     * @TODO Write simulator if planning on using this.
     *
     * @param workpoolId
     * @return
     * @throws WpException
     */
    public Lease acquire(Long workpoolId) throws WpException {
        try {
            return _rest.postForObject(baseUrl() + "/workpools/leases/acquire/{workpoolId}", "", Lease.class,
                    workpoolId);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Releases a previously acquired lease of a workpool instance.
     *
     * @TODO Write simulator if planning on using this.
     * @TODO Should this really be a POST or PUT? Verify if plan to use this.
     *
     * @param workpoolId
     * @param leaseId
     * @throws WpException
     */
    public void release(Long workpoolId, Long leaseId) throws WpException {
        try {
            _rest.postForObject(baseUrl() + "/workpools/{workpoolId}/leases/{id}/release", null, null, workpoolId,
                    leaseId);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Used to create a workpool. This call can create workpools of Full,
     * linked, Custom types.
     *
     * NOTE: The created workpool or the Id is not returned as its not needed
     * at this point in time. If needed @see VmImage.createVmImage()
     *
     * @param workpool
     * @return
     * @throws WpException, AfConflictException
     */
    public Long createWorkpool(Workpool workpool) throws WpException, AfConflictException {
        try {
            // This method does not return the
            URI uri = _rest.postForLocation(baseUrl() + "/workpools", workpool);

            return Long.valueOf(AfUtil.extractLastURIToken(uri));
        } catch (HttpStatusCodeException ex) {
            if (ex.getStatusCode() == HttpStatus.CONFLICT) {
                throw new AfConflictException("CONFLICT_NAME: " + ex.getMessage());
            }
            throw new WpException("Workpool cannot be created: " + ex.getMessage());
        } catch (RestClientException e) {
            throw new WpException("Workpool cannot be created: " + e.getMessage());
        }
    }

    /**
     * Used to update a VM Image. Name field can be updated.
     *
     * @param workpool
     * @throws WpException
     */
    public void updateWorkpool(Workpool workpool) throws WpException, AfNotFoundException, AfConflictException {
        Long id = workpool.getId();
        try {
            _rest.put(baseUrl() + "/workpools/{id}", workpool, id);
        } catch (HttpStatusCodeException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new AfNotFoundException("NOT_FOUND: " + ex.getMessage());
            } else if (ex.getStatusCode() == HttpStatus.CONFLICT) {
                throw new AfConflictException("CONFLICT_NAME: " + ex.getMessage());
            }
            throw new WpException("Workpool cannot be updated: " + ex.getMessage());
        } catch (RestClientException e) {
            throw new WpException("Workpool cannot be updated: " + e.getMessage());
        }
    }

    /*****
     * The following methods constitute for the management of VM Image.
     * These should be abstracted in the backend, so the transactions across creation
     * of Image and workpool happen together.
     *****/

    /**
     * Get all known VM images.
     * @return
     * @throws WpException
     */
    public List<VmImage> getAllImages() throws WpException {
        try {
            VmImage[] objects = _rest.getForObject(baseUrl() + "/vmimages", VmImage[].class);

            return Arrays.asList(objects);
        } catch (RestClientException ex) {
            _log.error("Failed to get images from VmImage service", ex);
            throw new WpException(ex);
        } catch (Exception ex) {
            _log.error("Failed to get images from VmImage service", ex);
            throw new WpException(ex);
        }

    }

    /**
     * Returns the VmImage identified by the id passed.
     *
     * @param id
     * @return
     * @throws WpException
     */
    public VmImage getVmImageById(Long id) throws WpException, AfNotFoundException {
        if (id == null) {
            throw new WpException("Empty input");
        }
        try {
            return _rest.getForObject(baseUrl() + "/vmimages/{id}", VmImage.class, id);
        } catch (HttpStatusCodeException ex) {
            if (ex.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new AfNotFoundException("NOT_FOUND: " + ex.getMessage());
            }
            throw new WpException(ex);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Returns the VmImage identified by the parameter name.
     *
     * @TODO Eventually have a REST API to do this look up. For now using a less
     * performant way. Leaving the simulator as is to support lookup by name.
     *
     * @param name
     * @return
     * @throws WpException
     */
    public VmImage getVmImageByName(String name) throws WpException, AfNotFoundException {
        // Validate input.
        if (name == null) {
            throw new WpException("Empty input");
        }
        List<VmImage> imageList = getAllImages();
        if (!CollectionUtils.isEmpty(imageList)) {
            for (VmImage i : imageList)
                if (name.equals(i.getName())) {
                    return i;
                }
        }
        throw new AfNotFoundException("NOT_FOUND: " + "VM Image '" + name + "' is not found");
    }

    /**
     * Deletes the VmImage by id
     *
     * @param imageId
     * @param deleteMethod
     */
    public void deleteVmImage(Long imageId, DeleteMethod deleteMethod) throws WpException {
        try {
            _rest.delete(baseUrl() + "/vmimages/{imageId}?deleteMethod={deleteMethod}", imageId, deleteMethod);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Used to create a VM Image.
     *
     * @param image
     * @return
     * @throws WpException
     */
    public Long createVmImage(VmImage image) throws WpException {
        try {
            URI uri = _rest.postForLocation(baseUrl() + "/vmimages", image);

            if (uri == null) {
                _log.debug("uri is null");
                throw new WpException("uri is null after creating vmimage");
            }
            return Long.valueOf(AfUtil.extractLastURIToken(uri));
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * Used to update a VM Image. Name field can be updated.
     *
     * @param image
     * @throws WpException
     */
    public void updateVmImage(VmImage image) throws WpException {
        Long id = image.getId();
        try {
            _rest.put(baseUrl() + "/vmimages/{id}", image, id);
        } catch (RestClientException e) {
            throw new WpException(e);
        }
    }

    /**
     * A helper method that checks if the default is not set, and if so,
     * sets the default to the workpoolId passed.
     *
     * @param workpoolId
     */
    public void setIfNoDefaultExists(Long workpoolId) {
        if (!hasDefault()) {
            _config.setValue(ConfigRegistryConstants.WORKPOOL_DEFAULT_WORKPOOL, workpoolId.toString());
        }
    }

    /**
     * Helper method that fetches the default workpool if one exists.
     *
     * @return
     * @throws WpException
     * @throws AfNotFoundException - When no default workpool is set.
     */
    @Nonnull
    public Workpool getDefault() throws WpException, AfNotFoundException {
        if (hasDefault()) {
            Long defaultWp = Long.valueOf(_config.getLong(ConfigRegistryConstants.WORKPOOL_DEFAULT_WORKPOOL));
            return getWorkpoolById(defaultWp);
        }
        throw new AfNotFoundException("Default workpool does not exist");
    }

    /**
     * Check if the param is the default.
     * @param workpool
     * @return True if a default has been selected, and is the one passed.
     */
    public boolean isDefault(Workpool workpool) {
        if (workpool == null) {
            return false;
        }
        String configKey = _config.getString(ConfigRegistryConstants.WORKPOOL_DEFAULT_WORKPOOL);
        return String.valueOf(workpool.getId()).equals(configKey);
    }

    /**
     * Check whether a default workpool exists or not.
     * @return true if the default workpool is not empty
     */
    public boolean hasDefault() {
        /* Set the first workpool as default */
        String defaultWp = _config.getString(ConfigRegistryConstants.WORKPOOL_DEFAULT_WORKPOOL);
        return !StringUtils.isEmpty(defaultWp);
    }

}