content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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.cloud.hypervisor.xenserver.resource;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  
  import org.apache.xmlrpc.XmlRpcException;
  
  import com.cloud.agent.api.StartCommand;
  import com.cloud.agent.api.StartupRoutingCommand;
  import com.cloud.agent.api.VgpuTypesInfo;
  import com.cloud.agent.api.to.GPUDeviceTO;
  import com.xensource.xenapi.Connection;
  import com.xensource.xenapi.GPUGroup;
  import com.xensource.xenapi.Host;
  import com.xensource.xenapi.PGPU;
  import com.xensource.xenapi.Types.XenAPIException;
  import com.xensource.xenapi.VGPU;
  import com.xensource.xenapi.VGPUType;
  import com.xensource.xenapi.VGPUType.Record;
  import com.xensource.xenapi.VM;
  
  public class XenServer620SP1Resource extends XenServer620Resource {
  
  
      @Override
      protected void fillHostInfo(final Connection conn, final StartupRoutingCommand cmd) {
          super.fillHostInfo(conn, cmd);
          try {
              final HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = getGPUGroupDetails(conn);
              cmd.setGpuGroupDetails(groupDetails);
              if (groupDetails != null && !groupDetails.isEmpty()) {
                  cmd.setHostTags("GPU");
              }
          } catch (final Exception e) {
              if (logger.isDebugEnabled()) {
                  logger.debug("Error while getting GPU device info from host " + cmd.getName(), e);
              }
          }
      }
  
      @Override
      public HashMap<String, HashMap<String, VgpuTypesInfo>> getGPUGroupDetails(final Connection conn) throws XenAPIException, XmlRpcException {
          final HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
          final Host host = Host.getByUuid(conn, _host.getUuid());
          final Set<PGPU> pgpus = host.getPGPUs(conn);
          final Iterator<PGPU> iter = pgpus.iterator();
          while (iter.hasNext()) {
              final PGPU pgpu = iter.next();
              final GPUGroup gpuGroup = pgpu.getGPUGroup(conn);
              final Set<VGPUType> enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn);
              final String groupName = gpuGroup.getNameLabel(conn);
              HashMap<String, VgpuTypesInfo> gpuCapacity = new HashMap<String, VgpuTypesInfo>();
              if (groupDetails.get(groupName) != null) {
                  gpuCapacity = groupDetails.get(groupName);
              }
              // Get remaining capacity of all the enabled VGPU in a PGPU
              if(enabledVGPUTypes != null) {
                  final Iterator<VGPUType> it = enabledVGPUTypes.iterator();
                  while (it.hasNext()) {
                      final VGPUType type = it.next();
                      final Record record = type.getRecord(conn);
                      Long remainingCapacity = pgpu.getRemainingCapacity(conn, type);
                      Long maxCapacity = pgpu.getSupportedVGPUMaxCapacities(conn).get(type);
                      VgpuTypesInfo entry;
                      if ((entry = gpuCapacity.get(record.modelName)) != null) {
                          remainingCapacity += entry.getRemainingCapacity();
                          maxCapacity += entry.getMaxCapacity();
                          entry.setRemainingCapacity(remainingCapacity);
                          entry.setMaxVmCapacity(maxCapacity);
                          gpuCapacity.put(record.modelName, entry);
                      } else {
                          final VgpuTypesInfo vgpuTypeRecord = new VgpuTypesInfo(null, record.modelName, record.framebufferSize, record.maxHeads,
                                  record.maxResolutionX, record.maxResolutionY, maxCapacity, remainingCapacity, maxCapacity);
                          gpuCapacity.put(record.modelName, vgpuTypeRecord);
                      }
                  }
              }
              groupDetails.put(groupName, gpuCapacity);
          }
          return groupDetails;
      }
  
      @Override
      public void createVGPU(final Connection conn, final StartCommand cmd, final VM vm, final GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException {
          if (logger.isDebugEnabled()) {
              logger.debug("Creating VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] in gpu group" + gpuDevice.getGpuGroup()
                      + " for VM " + cmd.getVirtualMachine().getName());
          }
  
          final Set<GPUGroup> groups = GPUGroup.getByNameLabel(conn, gpuDevice.getGpuGroup());
          assert groups.size() == 1 : "Should only have 1 group but found " + groups.size();
          final GPUGroup gpuGroup = groups.iterator().next();
  
          final Set<VGPUType> vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn);
          final Iterator<VGPUType> iter = vgpuTypes.iterator();
          VGPUType vgpuType = null;
          while (iter.hasNext()) {
              final VGPUType entry = iter.next();
              if (entry.getModelName(conn).equals(gpuDevice.getVgpuType())) {
                  vgpuType = entry;
              }
          }
          final String device = "0"; // Only allow device = "0" for now, as XenServer supports just a single vGPU per VM.
          final Map<String, String> other_config = new HashMap<String, String>();
          VGPU.create(conn, vm, gpuGroup, device, other_config, vgpuType);
  
          if (logger.isDebugEnabled()) {
              logger.debug("Created VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] for VM " + cmd.getVirtualMachine().getName());
          }
          // Calculate and set remaining GPU capacity in the host.
          cmd.getVirtualMachine().getGpuDevice().setGroupDetails(getGPUGroupDetails(conn));
      }
  }
  