http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/StoragePlugin.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/StoragePlugin.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/StoragePlugin.java new file mode 100644 index 0000000..24c774a --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/StoragePlugin.java @@ -0,0 +1,882 @@ +/******************************************************************************* + * 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.ovm3.objects; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.w3c.dom.Document; + +/* + * should become an interface implementation + */ +public class StoragePlugin extends OvmObject { + private static final String EMPTY_STRING = ""; + private static final String PLUGINPATH = "//Discover_Storage_Plugins_Result/storage_plugin_info_list/storage_plugin_info"; + private static final String NFSPLUGIN = "oracle.generic.NFSPlugin.GenericNFSPlugin"; + private static final String FILESYS = "FileSys"; + private static final String STATUS = "status"; + private static final String UUID = "uuid"; + private static final String SSUUID = "ss_uuid"; + private static final String SIZE = "size"; + private static final String FREESIZE = "free_sz"; + private static final String STATE = "state"; + private static final String ACCESSGROUPNAMES = "access_grp_names"; + private static final String ACCESSPATH = "access_path"; + private static final String NAME = "name"; + private static final String MOUNTOPTIONS = "mount_options"; + private static final String ADMINUSER = "admin_user"; + private static final String ADMINHOST = "admin_host"; + private static final String TOTALSIZE = "total_sz"; + private static final String ADMINPASSWORD = "admin_passwd"; + private static final String STORAGEDESC = "storage_desc"; + private static final String ACCESSHOST = "access_host"; + private static final String STORAGETYPE = "storage_type"; + private static final String ALLOCSIZE = "alloc_sz"; + private static final String ACCESSGROUPS = "access_grps"; + private static final String USEDSIZE = "used_sz"; + private static final String FRTYPE = "fr_type"; + private static final String ONDISKSIZE = "ondisk_sz"; + private static final String FSUUID = "fs_uuid"; + private static final String FILEPATH = "file_path"; + private static final String FILESIZE = "file_sz"; + private static final Boolean ACTIVE = true; + + private String getPluginType = NFSPLUGIN; + private List<String> supportedPlugins = new ArrayList<String>(); + private final List<String> someList = new ArrayList<String>(); /* empty */ + private FileProperties fileProperties = new FileProperties(); + private StorageDetails storageDetails = new StorageDetails(); + private StorageServer storageServer = new StorageServer(); + + public StoragePlugin(Connection c) { + setClient(c); + } + + /* uuid has dashes here!, and ss_uuid is the relation to the storage source uuid */ + public class StorageDetails { + private Map<String, Object> storageDetails = new HashMap<String, Object>() { + { + put(STATUS, EMPTY_STRING); + put(UUID, EMPTY_STRING); + put(SSUUID, EMPTY_STRING); + put(SIZE, EMPTY_STRING); + put(FREESIZE, 0); + put(STATE, 0); + put(ACCESSGROUPNAMES, new ArrayList<String>()); + put(ACCESSPATH, EMPTY_STRING); + put(NAME, EMPTY_STRING); + put(MOUNTOPTIONS, new ArrayList<String>()); + } + }; + public Map<String, Object> getDetails() { + return storageDetails; + } + public void setDetails(Map<String, Object> details) { + storageDetails = details; + } + public void setSize(String val) { + storageDetails.put(SIZE, val); + } + public String getSize() { + return (String) storageDetails.get(SIZE); + } + public void setFreeSize(String val) { + storageDetails.put(FREESIZE, val); + } + public String getFreeSize() { + return (String) storageDetails.get(FREESIZE); + } + public void setState(Integer val) { + storageDetails.put(STATE, val); + } + public Integer getState() { + return (Integer) storageDetails.get(STATE); + } + public void setStatus(String val) { + storageDetails.put(STATUS, val); + } + public String getStatus() { + return (String) storageDetails.get(STATUS); + } + /* format depends on storagesource type ? */ + public void setAccessPath(String val) { + storageDetails.put(ACCESSPATH, val); + } + public String getAccessPath() { + return (String) storageDetails.get(ACCESSPATH); + } + public void setName(String val) { + storageDetails.put(NAME, val); + } + public String getName() { + return (String) storageDetails.get(NAME); + } + public void setUuid(String val) throws Ovm3ResourceException { + if (!val.contains("-")) { + throw new Ovm3ResourceException("Storage Details UUID should contain dashes: " + val); + } + storageDetails.put(UUID, val); + } + public String getUuid() { + return (String) storageDetails.get(UUID); + } + public void setDetailsRelationalUuid(String val) throws Ovm3ResourceException { + if (val.contains("-")) { + throw new Ovm3ResourceException("Storage Details UUID that relates to Storage Source should notcontain dashes: " + val); + } + storageDetails.put(SSUUID, val); + } + public String getDetailsRelationalUuid() { + return (String) storageDetails.get(SSUUID); + } + public void setAccessGroupNames(List<String> l) { + storageDetails.put(ACCESSGROUPNAMES, l); + } + public List<String> getAccessGroupNames() { + return (List<String>) storageDetails.get(ACCESSGROUPNAMES); + } + public void setMountOptions(List<String> l) { + storageDetails.put(MOUNTOPTIONS, l); + } + public List<String> getMountOptions() { + return (List<String>) storageDetails.get(MOUNTOPTIONS); + } + } + + /* mind you uuid has NO dashes here */ + public class StorageServer { + private Map<String, Object> storageSource = new HashMap<String, Object>() { + { + put(STATUS, EMPTY_STRING); + put(ADMINUSER, EMPTY_STRING); + put(ADMINHOST, EMPTY_STRING); + put(UUID, EMPTY_STRING); + put(TOTALSIZE, 0); + put(ADMINPASSWORD, EMPTY_STRING); + put(STORAGEDESC, EMPTY_STRING); + put(FREESIZE, 0); + put(ACCESSHOST, EMPTY_STRING); + put(STORAGETYPE, EMPTY_STRING); + put(ALLOCSIZE, 0); + put(ACCESSGROUPS, new ArrayList<String>()); + put(USEDSIZE, 0); + put(NAME, EMPTY_STRING); + } + }; + public Map<String, Object> getDetails() { + return storageSource; + } + public void setDetails(Map<String, Object> details) { + storageSource = details; + } + public void setAccessGroups(List<String> l) { + storageSource.put(ACCESSGROUPS, l); + } + public List<String> getAccessGroups() { + return (List<String>) storageSource.get(ACCESSGROUPS); + } + public void setStatus(String val) { + storageSource.put(STATUS, val); + } + public String getStatus() { + return (String) storageSource.get(STATUS); + } + public void setAdminUser(String val) { + storageSource.put(ADMINUSER, val); + } + public String getAdminUser() { + return (String) storageSource.get(ADMINUSER); + } + public void setAdminHost(String val) { + storageSource.put(ADMINHOST, val); + } + public String getAdminHost() { + return (String) storageSource.get(ADMINHOST); + } + public void setUuid(String val) throws Ovm3ResourceException { + if (val.contains("-")) { + throw new Ovm3ResourceException("Storage Source UUID should not contain dashes: " + val); + } + storageSource.put(UUID, val); + } + public String getUuid() { + return (String) storageSource.get(UUID); + } + public String getTotalSize() { + return (String) storageSource.get(TOTALSIZE); + } + public void setTotalSize(Integer val) { + storageSource.put(TOTALSIZE, val); + } + public void setAdminPassword(String val) { + storageSource.put("admin_password", val); + } + public String getAdminPassword() { + return (String) storageSource.get("admin_password"); + } + public void setDescription(String val) { + storageSource.put(STORAGEDESC, val); + } + public String getDescription() { + return (String) storageSource.get(STORAGEDESC); + } + public String getFreeSize() { + return (String) storageSource.get(FREESIZE); + } + public void setFreeSize(Integer val) { + storageSource.put(FREESIZE, val); + } + public void setAccessHost(String val) { + storageSource.put(ACCESSHOST, val); + } + public String getAccessHost() { + return (String) storageSource.get(ACCESSHOST); + } + public void setStorageType(String val) { + storageSource.put(STORAGETYPE, val); + } + public String getStorageType() { + return (String) storageSource.get(STORAGETYPE); + } + public void setAllocationSize(Integer val) { + storageSource.put(ALLOCSIZE, val); + } + public Integer getAllocationSize() { + return (Integer) storageSource.get(ALLOCSIZE); + } + public void setUsedSize(Integer val) { + storageSource.put(USEDSIZE, val); + } + public Integer getUsedSize() { + return (Integer) storageSource.get(USEDSIZE); + } + public void setName(String val) { + storageSource.put(NAME, val); + } + public String getName() { + return (String) storageSource.get(NAME); + } + } + + public class FileProperties { + private Map<String, Object> fileProperties = new HashMap<String, Object>() { + { + put(FRTYPE, EMPTY_STRING); + put(ONDISKSIZE, EMPTY_STRING); + put(FSUUID, EMPTY_STRING); + put(FILEPATH, EMPTY_STRING); + put(FILESIZE, EMPTY_STRING); + } + }; + public Map<String, Object> getProperties() { + return fileProperties; + } + public void setProperties(Map<String, Object> props) { + fileProperties = props; + } + public String getName() { + return (String) fileProperties.get(FILEPATH); + } + public String setName(String f) { + return (String) fileProperties.put(FILEPATH, f); + } + public String setType(String t) { + return (String) fileProperties.put(FRTYPE, t); + } + public String getType() { + return (String) fileProperties.get(FRTYPE); + } + public void setSize(Long t) { + fileProperties.put(FILESIZE, t); + } + public Long getSize() { + return Long.parseLong((String) fileProperties.get(FILESIZE)); + } + public String setOnDiskSize(String t) { + return (String) fileProperties.put(ONDISKSIZE, t); + } + public String getOnDiskSize() { + return (String) fileProperties.get(ONDISKSIZE); + } + public String setUuid(String t) { + return (String) fileProperties.put(FSUUID, t); + } + public String getUuid() { + return (String) fileProperties.get(FSUUID); + } + } + + public String getPluginType() { + return getPluginType; + } + private Boolean setPluginType(String val) throws Ovm3ResourceException { + for(String plugin : discoverStoragePlugins()) { + if (plugin.matches("(?i:.*"+val+".*)")) { + getPluginType = plugin; + return true; + } + } + return false; + } + public Boolean setISCSI() throws Ovm3ResourceException { + return setPluginType("SCSI"); + } + public Boolean setOCFS2() throws Ovm3ResourceException { + return setPluginType("OCFS2"); + } + public Boolean setNFS() throws Ovm3ResourceException { + return setPluginType("NFS"); + } + + /* Actions for the storage plugin */ + /* + * storage_plugin_resizeFileSystem, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getStatus, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None meh ? + */ + + /* + * storage_plugin_validate, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_setQoS, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * now only for files + * storage_plugin_create, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None - calls resize secretly.. after "create" + */ + public FileProperties storagePluginCreate(String poolUuid, String host, + String file, Long size, Boolean dir) throws Ovm3ResourceException{ + /* this is correct ordering stuff and correct naming!!! */ + String uuid = deDash(poolUuid); + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + FileProperties fp = new FileProperties(); + ss.setUuid(uuid); + ss.setStorageType(FILESYS); + ss.setAccessHost(host); + sd.setUuid(poolUuid); + sd.setDetailsRelationalUuid(uuid); + sd.setState(2); + String type = "File"; + if (dir) { + type = "Directory"; + } + fp.setProperties((HashMap<String, Object>) callWrapper("storage_plugin_create", + getPluginType, ss.getDetails(), + sd.getDetails(), file, type, size)); + return fp; + } + + /* + * storage_plugin_createAccessGroups, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_deviceTeardown, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_startPresent, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_listFileSystems, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + public Boolean storagePluginListFs(String host) throws Ovm3ResourceException { + StorageServer ss = new StorageServer(); + ss.setAccessHost(host); + ss.setStorageType(FILESYS); + ss.setDetails((Map<String, Object>) callWrapper("storage_plugin_listFileSystems", + getPluginType, ss.getDetails())); + return true; + } + + /* + * storage_plugin_getFileSystemCloneLimits, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getQoSList, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_stopPresent, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_isCloneable, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /** + * . storage_plugin_mount, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + public final StorageDetails storagePluginMountNFS(String nfsHost, String nfsRemotePath, + String mntUuid, String mountPoint) throws Ovm3ResourceException { + String propUuid = deDash(mntUuid); + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + ss.setUuid(propUuid); + ss.setName(propUuid); + ss.setAccessHost(nfsHost); + sd.setDetailsRelationalUuid(propUuid); + sd.setUuid(mntUuid); + sd.setAccessPath(nfsHost + ":" + nfsRemotePath); + if (!mountPoint.contains(mntUuid)) { + mountPoint += File.separator + mntUuid; + } + sd.setDetails((HashMap<String, Object>) callWrapper( + "storage_plugin_mount", getPluginType, ss.getDetails(), + sd.getDetails(), mountPoint, EMPTY_STRING, ACTIVE, + someList)); + /* this magically means it's already mounted.... + * double check */ + if (sd.getDetails() == null) { + sd = storagePluginGetFileSystemInfo(propUuid, + mntUuid, nfsHost, nfsRemotePath); + } + if (EMPTY_STRING.contains(ss.getUuid())) { + throw new Ovm3ResourceException("Unable to mount NFS FileSystem"); + } + return sd; + } + + /** + * . storage_plugin_unmount, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + * + * @return boolean + * + */ + public final Boolean storagePluginUnmountNFS(String nfsHost, String remotePath, String mntUuid, String localPath) throws Ovm3ResourceException { + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + sd.setUuid(mntUuid); + sd.setDetailsRelationalUuid(deDash(mntUuid)); + ss.setUuid(deDash(mntUuid)); + ss.setAccessHost(nfsHost); + sd.setAccessPath(nfsHost + ":" + remotePath); + sd.setState(1); + ss.setStorageType(FILESYS); + String mountPoint = localPath + File.separator + mntUuid; + callWrapper("storage_plugin_unmount", getPluginType, + ss.getDetails(), sd.getDetails(), mountPoint, ACTIVE); + return true; + } + + /* + * storage_plugin_resize, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_deviceSizeRefresh, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + /* + * storage_plugin_getStorageNames, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_splitClone, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_destroyFileSystem, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_snapRestore, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_updateSERecords, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getSnapLimits, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * discover_storage_plugins, <class 'agent.api.storageplugin.StoragePlugin'> + */ + public List<String> discoverStoragePlugins() throws Ovm3ResourceException{ + supportedPlugins = new ArrayList<String>(); + Object result = callWrapper("discover_storage_plugins"); + if (result == null) { + return supportedPlugins; + } + Document xmlDocument = prepParse((String) result); + supportedPlugins.addAll(xmlToList(PLUGINPATH + "/@plugin_impl_name", xmlDocument)); + return supportedPlugins; + } + + private Map<String,String> checkStoragePluginDetails(String plugin, Boolean ability) throws Ovm3ResourceException { + Object result = callWrapper("discover_storage_plugins"); + Document xmlDocument = prepParse((String) result); + if (discoverStoragePlugins().contains(plugin)) { + String details = PLUGINPATH + "[@plugin_impl_name='" + plugin + "']"; + if (ability) { + return xmlToMap(details + "/abilities", xmlDocument); + } else { + return xmlToMap(details, xmlDocument); + } + } else { + throw new Ovm3ResourceException("StoragePlugin should be one of: " + supportedPlugins); + } + } + + private String checkStoragePluginBoth(String type, String property, Boolean ab) throws Ovm3ResourceException{ + String val = checkStoragePluginDetails(type, ab).get(property); + if (val == null) { + throw new Ovm3ResourceException("StoragePlugin " + type + " has no " + property); + } + return val; + } + + public String checkStoragePluginAbility(String type, String property) throws Ovm3ResourceException { + return checkStoragePluginBoth(type, property, true); + } + public String checkStoragePluginProperties(String type, String property) throws Ovm3ResourceException { + return checkStoragePluginBoth(type, property, false); + } + + /* + * storage_plugin_deviceResize, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getCloneLimits, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * INFO: is used for files and dirs..., we only implement files for now... + * storage_plugin_destroy, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + public Boolean storagePluginDestroy(String poolUuid, String file) throws Ovm3ResourceException { + String uuid = deDash(poolUuid); + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + FileProperties fp = new FileProperties(); + ss.setUuid(uuid); + sd.setDetailsRelationalUuid(uuid); + sd.setUuid(poolUuid); + fp.setType("file"); + fp.setUuid(poolUuid); + fp.setName(file); + return nullIsTrueCallWrapper( + "storage_plugin_destroy", getPluginType, ss.getDetails(), + sd.getDetails(), fp.getProperties()); + } + + /* + * storage_plugin_isSnapable, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getDetailsInfo, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_removeFromAccessGroup, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_renameAccessGroup, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_stop, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_createMultiSnap, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getCurrentSnaps, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getFileInfo, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + public FileProperties storagePluginGetFileInfo(String poolUuid, String host, + String file) throws Ovm3ResourceException { + /* file path is the full path */ + String uuid = deDash(poolUuid); + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + FileProperties fp = new FileProperties(); + ss.setUuid(uuid); + ss.setAccessHost(host); + sd.setUuid(poolUuid); + sd.setDetailsRelationalUuid(uuid); + sd.setState(1); + fp.setName(file); + fp.setProperties((HashMap<String, Object>) callWrapper( + "storage_plugin_getFileInfo", + getPluginType, + ss.getDetails(), + sd.getDetails(), + fp.getProperties())); + if ("".equals(fp.getName())) { + throw new Ovm3ResourceException("Unable to get file info for " + file); + } + return fp; + } + + /* + * Should do some input checking of ss and base + * storage_plugin_getFileSystemInfo, + * <class 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - + * default: None requires a minumum of uuid, access_host, storage_type + * ss_uuid, access_path, uuid (the ss + */ + public StorageDetails storagePluginGetFileSystemInfo(String propUuid, + String mntUuid, String nfsHost, String nfsRemotePath) throws Ovm3ResourceException{ + /* clean the props */ + StorageServer ss = new StorageServer(); + StorageDetails sd = new StorageDetails(); + new FileProperties(); + ss.setUuid(propUuid); + sd.setDetailsRelationalUuid(propUuid); + sd.setUuid(mntUuid); + ss.setAccessHost(nfsHost); + if (nfsRemotePath.contains(nfsHost + ":")) { + sd.setAccessPath(nfsRemotePath); + } else { + sd.setAccessPath(nfsHost + ":" + nfsRemotePath); + } + ss.setStorageType(FILESYS); + sd.setDetails((HashMap<String, Object>) callWrapper( + "storage_plugin_getFileSystemInfo", getPluginType, + ss.getDetails(), sd.getDetails())); + return sd; + } + public StorageDetails getStorageDetails() { + return storageDetails; + } + public void setStorageDetails(StorageDetails storageDetails) { + this.storageDetails = storageDetails; + } + public StorageServer getStorageServer() { + return storageServer; + } + public void setStorageServer(StorageServer storageServer) { + this.storageServer = storageServer; + } + public FileProperties getFileProperties() { + return fileProperties; + } + public void setFileProperties(FileProperties fileProperties) { + this.fileProperties = fileProperties; + } + + /* + * storage_plugin_clone, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_list, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_getInfo, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_snapRemove, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getCapabilities, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_createSnap, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getFileSystemSnapLimits, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_remove, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_getCurrentClones, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_online, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_isRestorable, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_iSCSI_logoutTarget, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: target - default: None + * argument: portal - default: None + */ + + /* + * storage_plugin_discover, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_start, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_removeAccessGroups, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_refresh, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_getAccessGroups, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_iSCSI_deletePortal, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: portal - default: None + */ + + /* + * storage_plugin_createFileSystem, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_cloneFromSnap, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_addToAccessGroup, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_offline, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + */ + + /* + * storage_plugin_listMountPoints, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/Xen.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/Xen.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/Xen.java new file mode 100644 index 0000000..e582041 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/objects/Xen.java @@ -0,0 +1,996 @@ +/******************************************************************************* + * 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.ovm3.objects; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +public class Xen extends OvmObject { + private static final Logger LOGGER = Logger.getLogger(Xen.class); + private static final String VNCLISTEN = "vnclisten"; + private static final String MEMORY = "memory"; + private static final String MAXVCPUS = "maxvcpus"; + private static final String VCPUS = "vcpus"; + private static final String DOMTYPE = "OVM_domain_type"; + private static final String EXTRA = "extra"; + private Map<String, Vm> vmList = null; + private Vm defVm = new Vm(); + + public Xen(Connection c) { + setClient(c); + } + + /* + * a vm class.... Setting up a VM is different than retrieving one from OVM. + * It's either a list retrieval or + * /usr/lib64/python2.4/site-packages/agent/lib/xenvm.py + */ + public class Vm { + /* 'vfb': [ 'type=vnc,vncunused=1,vnclisten=127.0.0.1,keymap=en-us'] */ + private List<String> vmVncElement = new ArrayList<String>(); + private Map<String, String> vmVnc = new HashMap<String, String>() { + { + put("type", "vnc"); + put("vncunused", "1"); + put(VNCLISTEN, "127.0.0.1"); + put("keymap", "en-us"); + } + }; + + /* + * 'disk': [ + * 'file:/OVS/Repositories/0004fb0000030000aeaca859e4a8f8c0/VirtualDisks/0004fb0000120000c444117fd87ea251.img,xvda,w'] + */ + private List<String> vmDisks = new ArrayList<String>(); + private Map<String, String> vmDisk = new HashMap<String, String>() { + { + put("id", ""); + put("uuid", ""); + put("dev", ""); + put("bootable", "1"); + put("mode", "w"); + put("VDI", ""); + put("backend", "0"); + put("protocol", "x86_32-abi"); + put("uname", ""); + } + }; + + /* 'vif': [ 'mac=00:21:f6:00:00:00,bridge=c0a80100'] */ + private ArrayList<String> vmVifs = new ArrayList<String>(); + private Integer maxVifs = 7; + private String[] xvmVifs = new String[maxVifs -1]; + private String vmSimpleName = ""; + private String vmName = ""; + private String vmUuid = ""; + /* + * the pool the vm.cfg will live on, this is the same as the primary + * storage pool (should be unified with disk pool ?) + */ + private String vmPrimaryPoolUuid = ""; + private String vmOnReboot = "restart"; + /* weight is relative for all VMs compared to each other */ + private int vmCpuWeight = 27500; + /* minimum memory allowed */ + private int vmMemory = 256; + private int vmCpuCap = 0; + /* dynam scaling for cpus */ + private int vmMaxVcpus = 0; + /* default to 1, can't be higher than maxvCpus */ + private int vmVcpus = 1; + /* high available */ + private Boolean vmHa = false; + private String vmDescription = ""; + private String vmOnPoweroff = "destroy"; + private String vmOnCrash = "restart"; + private String vmBootloader = "/usr/bin/pygrub"; + private String vmBootArgs = ""; + private String vmExtra = ""; + /* default to linux */ + private String vmOs = "Other Linux"; + private String vmCpuCompatGroup = ""; + /* pv is default */ + private String vmDomainType = "xen_pvm"; + /* start counting disks at A -> 0 */ + private int diskZero = 97; + private int diskCount = diskZero; + + private Map<String, Object> vmParams = new HashMap<String, Object>() { + { + put("vif", vmVifs); + put("OVM_simple_name", vmSimpleName); + put("disk", vmDisks); + put("bootargs", vmBootArgs); + put("uuid", vmUuid); + put("on_reboot", vmOnReboot); + put("cpu_weight", vmCpuWeight); + put(MEMORY, vmMemory); + put("cpu_cap", vmCpuCap); + put(MAXVCPUS, vmMaxVcpus); + put("OVM_high_availability", vmHa); + put("OVM_description", vmDescription); + put("on_poweroff", vmOnPoweroff); + put("on_crash", vmOnCrash); + put("bootloader", vmBootloader); + put("name", vmName); + put("guest_os_type", vmOs); + put("vfb", vmVncElement); + put(VCPUS, vmVcpus); + put("OVM_cpu_compat_group", vmCpuCompatGroup); + put(DOMTYPE, vmDomainType); + put(EXTRA, vmExtra); + } + }; + + public boolean isControlDomain() { + if ("Domain-0".equals(this.getVmName())) { + return true; + } + return false; + } + + public boolean setPrimaryPoolUuid(String poolId) { + this.vmPrimaryPoolUuid = poolId; + return true; + } + + public String getPrimaryPoolUuid() throws Ovm3ResourceException { + if ("".equals(this.vmPrimaryPoolUuid)) { + return this.getVmRootDiskPoolId(); + } else { + return this.vmPrimaryPoolUuid; + } + } + + public Map<String, Object> getVmParams() { + return this.vmParams; + } + + public void setVmParams(Map<String, Object> params) { + this.vmParams = params; + } + + public boolean setVmExtra(final String args) { + vmParams.put(EXTRA, args); + return true; + } + + public String getVmExtra() { + return (String) vmParams.get(EXTRA); + } + + public String getVmBootArgs() { + return (String) vmParams.get("bootloader_args"); + } + + public void setVmMaxCpus(Integer val) { + vmParams.put(MAXVCPUS, val); + } + + public Integer getVmMaxCpus() { + return (Integer) vmParams.get(MAXVCPUS); + } + + public void setVmCpus(Integer val) { + if (getVmMaxCpus() == 0 || getVmMaxCpus() >= val) { + vmParams.put(VCPUS, val); + } else if (getVmMaxCpus() < val) { + setVmCpus(getVmMaxCpus()); + } + } + + public Integer getVmCpus() { + return (Integer) vmParams.get(VCPUS); + } + + public Boolean setVmMemory(long memory) { + vmParams.put(MEMORY, Long.toString(memory)); + return true; + } + + public long getVmMemory() { + return Integer.parseInt((String) vmParams.get(MEMORY)); + } + + public Boolean setVmDomainType(String domtype) { + vmParams.put(DOMTYPE, domtype); + return true; + } + + /* iiiis this a good idea ? */ + public String getVmDomainType() { + String domType = (String) vmParams.get(DOMTYPE); + if (domType.equals(vmDomainType)) { + String builder = (String) vmParams.get("builder"); + if (builder == null || builder.contains("linux")) { + domType = "xen_pvm"; + } else { + domType = "hvm"; + } + } + return domType; + } + + public String getVmState() { + return (String) vmParams.get("state"); + } + + public Boolean setVmName(String name) { + vmParams.put("name", name); + vmParams.put("OVM_simple_name", name); + return true; + } + + public String getVmName() { + return (String) vmParams.get("name"); + } + + public Boolean setVmUuid(String uuid) { + vmParams.put("uuid", uuid); + return true; + } + + public String getVmUuid() { + return (String) vmParams.get("uuid"); + } + + public void setVmVncs(List<String> vncs) { + this.vmVncElement.addAll(vncs); + } + + public List<String> getVmVncs() { + return this.vmVncElement; + } + + public void setVmDisks(List<String> disks) { + this.vmDisks.addAll(disks); + } + + public List<String> getVmDisks() { + return this.vmDisks; + } + + public void setVmVifs(List<String> vifs) { + this.vmVifs.addAll(vifs); + } + + public List<String> getVmVifs() { + return this.vmVifs; + } + + public Integer getVifIdByMac(String mac) { + Integer c = 0; + for (final String entry : vmVifs) { + final String[] parts = entry.split(","); + final String[] macpart = parts[0].split("="); + assert macpart.length == 2 : "Invalid entry: " + entry; + if ("mac".equals(macpart[0]) && macpart[1].equals(mac)) { + return c; + } + c += 1; + } + LOGGER.debug("No vif matched mac: " + mac + " in " + vmVifs); + return -1; + } + public Integer getVifIdByIp(String ip) { + Integer c = 0; + for (final String entry : vmVifs) { + final String[] parts = entry.split(","); + final String[] ippart = parts[1].split("="); + assert ippart.length == 2 : "Invalid entry: " + entry; + if ("mac".equals(ippart[0]) && ippart[1].equals(ip)) { + return c; + } + c += 1; + } + LOGGER.debug("No vif matched ip: " + ip + " in " + vmVifs); + return -1; + } + + public Boolean addVif(Integer id, String bridge, String mac) { + if (getVifIdByMac(mac) > 0) { + LOGGER.debug("Already nic with mac present: " + mac); + return false; + } + String vif = "mac=" + mac + ",bridge=" + bridge; + xvmVifs[id] = vif; + return true; + } + + public boolean setupVifs() { + for (String vif : xvmVifs) { + if (vif != null && !vmVifs.contains(vif)) { + vmVifs.add(vif); + } + } + vmParams.put("vif", vmVifs); + return true; + } + + public Boolean removeVif(String bridge, String mac) { + List<String> newVifs = new ArrayList<String>(); + try { + String remove = "mac=" + mac + ",bridge=" + bridge; + for (String vif : getVmVifs()) { + if (vif.equals(remove)) { + LOGGER.debug("leaving out vif: " + remove); + } else { + LOGGER.debug("keeping vif: " + vif); + newVifs.add(vif); + } + } + vmParams.put("vif", newVifs); + } catch (Exception e) { + LOGGER.debug(e); + } + return true; + } + + /* 'file:/OVS/Repositories/d5f5a4480515467ca1638554f085b278/ISOs/e14c811ebbf84f0b8221e5b7404a554e.iso,hdc:cdrom,r' */ + /* device is coupled with vmtype enumerate and cdboot ? */ + public Boolean addRootDisk(String image) { + Boolean ret = false; + if (diskCount > diskZero) { + Integer oVmDisk = diskCount; + diskCount = diskZero; + ret = addDisk(image, "w"); + diskCount = oVmDisk; + } else { + ret = addDisk(image, "w"); + } + return ret; + } + + public Boolean addDataDisk(String image) { + /* + * w! means we're able to share the disk nice for clustered FS? + */ + return addDisk(image, "w!"); + } + + public Boolean addIso(String image) { + return addDisk(image, "r!"); + } + + private Boolean addDisk(String image, String mode) { + String devName = null; + /* better accounting then diskCount += 1 */ + diskCount = diskZero + vmDisks.size(); + if (getVmDomainType().contains("hvm")) { + diskCount += 2; + devName = Character.toString((char) diskCount); + } else { + devName = "xvd" + Character.toString((char) diskCount); + } + + /* check for iso, force mode and additions */ + if (image.endsWith(".iso")) { + devName = devName + ":cdrom"; + mode = "r"; + } + return addDiskToDisks(image, devName, mode); + } + + /* should be on device id too, or else we get random attaches... */ + private Boolean addDiskToDisks(String image, String devName, String mode) { + for (String disk : vmDisks) { + if (disk.contains(image)) { + LOGGER.debug(this.vmName + " already has disk " +image+ ":" + devName + ":" + mode); + return true; + } + } + vmDisks.add("file:" + image + "," + devName + "," + mode); + vmParams.put("disk", vmDisks); + return true; + } + + public Boolean removeDisk(String image) { + for (String disk : vmDisks) { + if (disk.contains(image)) { + vmDisks.remove(disk); + vmParams.put("disk", vmDisks); + return true; + } + } + LOGGER.debug("No disk found corresponding to image: " + image); + return false; + } + + /* The conflict between getVm and getVmConfig becomes clear */ + public String getVmRootDiskPoolId() throws Ovm3ResourceException { + String poolId = getVmDiskPoolId(0); + this.setPrimaryPoolUuid(poolId); + return poolId; + } + + private String getVmDiskPoolId(int disk) throws Ovm3ResourceException { + int fi = 3; + String diskPath = ""; + try { + diskPath = getVmDiskDetailFromMap(disk, "uname"); + } catch (NullPointerException e) { + throw new Ovm3ResourceException("No valid disk found for id: " + + disk); + } + String[] st = diskPath.split(File.separator); + return st[fi]; + } + + private String getVmDiskDetailFromMap(int disk, String dest) { + Map<String, Object[]> o = (Map<String, Object[]>) vmParams + .get("device"); + if (o == null) { + LOGGER.info("No devices found" + this.vmName); + return null; + } + vmDisk = (Map<String, String>) o.get("vbd")[disk]; + return vmDisk.get(dest); + } + + private boolean setVnc() { + List<String> vfb = new ArrayList<String>(); + for (final String key : vmVnc.keySet()) { + vfb.add(key + "=" + vmVnc.get(key)); + } + vmVncElement.add(StringUtils.join(vfb, ",")); + return true; + } + + public Boolean setVnc(String address, String password) { + setVncAddress(address); + setVncPassword(password); + return setVnc(); + } + + public void setVncUsed(String used) { + vmVnc.put("vncused", used); + } + + public String getVncUsed() { + return vmVnc.get("vncused"); + } + + public void setVncPassword(String pass) { + vmVnc.put("vncpasswd", pass); + } + + public String getVncPassword() { + return vmVnc.get("vncpasswd"); + } + + public void setVncAddress(String address) { + vmVnc.put(VNCLISTEN, address); + } + + public String getVncAddress() throws Ovm3ResourceException { + Integer port = getVncPort(); + if (port == null) { + return null; + } + return vmVnc.get(VNCLISTEN); + } + + public Integer getVncPort() throws Ovm3ResourceException { + if (getFromVncMap("port") != null) { + return Integer.parseInt(getFromVncMap("port")); + } + String vnc = getVncLocation(); + if (vnc != null && vnc.contains(":")) { + final String[] res = vnc.split(":"); + vmVnc.put(VNCLISTEN, res[0]); + vmVnc.put("port", res[1]); + return Integer.parseInt(res[1]); + } + throw new Ovm3ResourceException("No VNC port found"); + } + + public String getVncLocation() { + return getFromVncMap("location"); + } + + private String getFromVncMap(String el) { + Map<String, Object[]> o = (Map<String, Object[]>) vmParams + .get("device"); + if (o == null) { + return null; + } + vmVnc = (Map<String, String>) o.get("vfb")[0]; + if (vmVnc.containsKey(el)) { + return vmVnc.get(el); + } else { + return null; + } + } + + private Object get(String key) { + return vmParams.get(key); + } + } + + /* + * delete_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: assembly_id - + * default: None + */ + + /* + * unconfigure_template, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * template_id - default: None argument: params - default: None + */ + + /* + * sysrq_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: letter - default: None + */ + + /* + * list_vms, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None + */ + public Map<String, Vm> listVms() throws Ovm3ResourceException { + Object[] result = (Object[]) callWrapper("list_vms"); + if (result == null) { + LOGGER.debug("no vm results on list_vms"); + return null; + } + + try { + vmList = new HashMap<String, Vm>(); + for (Object x : result) { + /* put the vmparams in, as x is a hashmap */ + Vm vm = new Vm(); + vm.setVmParams((Map<String, Object>) x); + vmList.put((String) vm.get("name"), vm); + } + } catch (Exception e) { + String msg = "Unable to list VMs: " + e.getMessage(); + throw new Ovm3ResourceException(msg, e); + } + return vmList; + } + + /* + * this should become getVmConfig later... getVmConfig returns the + * configuration file, while getVm returns the "live" configuration. It + * makes perfect sense if you think about it..... ....long enough + */ + public Vm getRunningVmConfig(String name) throws Ovm3ResourceException { + return getRunningVmConfigs().get(name); + } + + public Map<String, Vm> getRunningVmConfigs() throws Ovm3ResourceException { + return listVms(); + } + + /* + * delete_vm_core, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: core_date - default: None + */ + + /* + * delete_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + public Boolean deleteVm(String repoId, String vmId) + throws Ovm3ResourceException { + return nullIsTrueCallWrapper("delete_vm", repoId, vmId); + } + + /* + * save_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: checkpoint - default: None + *//* add checkpoint */ + + /* + * configure_template, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * template_id - default: None argument: params - default: None + */ + + /* + * create_template, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: template_id - + * default: None argument: params - default: None + */ + + /* + * list_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + + public Boolean listVm(String repoId, String vmId) + throws Ovm3ResourceException { + defVm.setVmParams((Map<String, Object>) callWrapper("list_vm", repoId, + vmId)); + if (defVm.getVmParams() == null) { + LOGGER.debug("no vm results on list_vm"); + return false; + } + return true; + } + + /* + * dump_vm_core, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: live - default: None argument: crash - default: + * None argument: reset - default: None + */ + + /* + * assembly_del_file, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * assembly_id - default: None argument: filename - default: None + */ + + /* + * get_template_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * template_id - default: None + */ + + /* + * set_assembly_config_xml, <class 'agent.api.hypervisor.xenxm.Xen'> + * argument: self - default: None argument: repo_id - default: None + * argument: assembly_id - default: None argument: cfg - default: None + */ + + /* + * assembly_add_file, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * assembly_id - default: None argument: url - default: None argument: + * filename - default: None argument: option - default: None + */ + + /* + * send_to_guest, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: params - default: None + */ + + /* + * set_assembly_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * assembly_id - default: None argument: cfg - default: None + */ + + /* + * configure_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: params - default: None + */ + private Boolean configureVm(String repoId, String vmId, + Map<String, Object> params) throws Ovm3ResourceException { + return nullIsTrueCallWrapper("configure_vm", repoId, vmId, params); + } + + public Boolean configureVm(String repoId, String vmId) + throws Ovm3ResourceException { + return configureVm(repoId, vmId, this.defVm.getVmParams()); + } + + /* + * cleanup_migration_target, <class 'agent.api.hypervisor.xenxm.Xen'> + * argument: self - default: None argument: repo_id - default: None + * argument: vm_id - default: None + */ + + /* + * pause_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + public Boolean pauseVm(String repoId, String vmId) + throws Ovm3ResourceException { + return nullIsTrueCallWrapper("pause_vm", repoId, vmId); + } + + /* + * setup_migration_target, <class 'agent.api.hypervisor.xenxm.Xen'> + * argument: self - default: None argument: repo_id - default: None + * argument: vm_id - default: None + */ + + /* + * deploy_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: assembly_id - + * default: None argument: to_deploy - default: None argument: + * target_repo_id - default: None argument: option - default: None + */ + + /* + * stop_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: force - default: None + */ + public Boolean stopVm(String repoId, String vmId) + throws Ovm3ResourceException { + Object x = callWrapper("stop_vm", repoId, vmId, false); + if (x == null) { + return true; + } + return false; + } + + public Boolean stopVm(String repoId, String vmId, Boolean force) + throws Ovm3ResourceException { + Object x = callWrapper("stop_vm", repoId, vmId, force); + if (x == null) { + return true; + } + return false; + } + + /* + * set_template_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * template_id - default: None argument: params - default: None + */ + + /* + * assembly_rename_file, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * assembly_id - default: None argument: filename - default: None argument: + * new_filename - default: None + */ + + /* + * migrate_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: dest - default: None argument: live - default: + * None argument: ssl - default: None + */ + public Boolean migrateVm(String repoId, String vmId, String dest) + throws Ovm3ResourceException { + return nullIsTrueCallWrapper("migrate_vm", repoId, vmId, dest); + } + + public Boolean migrateVm(String repoId, String vmId, String dest, + boolean live, boolean ssl) throws Ovm3ResourceException { + Object x = callWrapper("migrate_vm", repoId, vmId, dest, live, ssl); + if (x == null) { + return true; + } + return false; + } + + /* + * configure_vm_ha, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: enable_ha - default: None + */ + public Boolean configureVmHa(String repoId, String vmId, Boolean ha) + throws Ovm3ResourceException { + Object x = callWrapper("configure_vm_ha", repoId, vmId, ha); + if (x == null) { + return true; + } + return false; + } + + /* + * create_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: params - default: None + */ + public Boolean createVm(String repoId, String vmId) + throws Ovm3ResourceException { + return nullIsTrueCallWrapper("create_vm", repoId, vmId, + defVm.getVmParams()); + } + + public Boolean createVm(String repoId, String vmId, + Map<String, Object> vmParams) throws Ovm3ResourceException { + return nullIsTrueCallWrapper("create_vm", repoId, vmId, vmParams); + } + + /* + * pack_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: assembly_id - + * default: None + */ + + /* + * restore_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: paused - default: None + */ + + /* + * start_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + public Boolean startVm(String repoId, String vmId) + throws Ovm3ResourceException { + return nullIsTrueCallWrapper("start_vm", repoId, vmId); + } + + /* + * unpause_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + + /* + * trigger_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: name - default: None argument: vcpu - default: + * None + */ + + /* + * set_vm_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: params - default: None + */ + + /* + * delete_template, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: template_id - + * default: None + */ + + /* + * reboot_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: wait - default: None + */ + public Boolean rebootVm(String repoId, String vmId, int wait) + throws Ovm3ResourceException { + Object x = callWrapper("reboot_vm", repoId, vmId, wait); + if (x == null) { + return true; + } + return false; + } + + public Boolean rebootVm(String repoId, String vmId) + throws Ovm3ResourceException { + Object x = callWrapper("reboot_vm", repoId, vmId, 3); + if (x == null) { + return true; + } + return false; + } + + /* + * unpack_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: assembly_id - + * default: None + */ + + /* + * get_vm_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + public Vm getVmConfig(String vmName) throws Ovm3ResourceException { + defVm = this.getRunningVmConfig(vmName); + if (defVm == null) { + LOGGER.debug("Unable to retrieve running config for " + vmName); + return defVm; + } + return getVmConfig(defVm.getVmRootDiskPoolId(), defVm.getVmUuid()); + } + + public Vm getVmConfig() { + return defVm; + } + + /* + * returns the configuration file contents, so we parse it for configuration + * alterations we might want to do (/$repo/VirtualMachines/$uuid/vm.cfg) + */ + public Vm getVmConfig(String repoId, String vmId) + throws Ovm3ResourceException { + try { + Xen.Vm nVm = new Xen.Vm(); + Map<String, Object[]> x = (Map<String, Object[]>) callWrapper( + "get_vm_config", repoId, vmId); + if (x == null) { + LOGGER.debug("Unable to find vm with id:" + vmId + " on repoId:" + repoId); + return nVm; + } + nVm.setVmVifs(Arrays.asList(Arrays.copyOf(x.get("vif"), + x.get("vif").length, String[].class))); + x.remove("vif"); + nVm.setVmDisks(Arrays.asList(Arrays.copyOf(x.get("disk"), + x.get("disk").length, String[].class))); + x.remove("disk"); + nVm.setVmVncs(Arrays.asList(Arrays.copyOf(x.get("vfb"), + x.get("vfb").length, String[].class))); + x.remove("vfb"); + Map<String, Object> remains = new HashMap<String, Object>(); + for (final Map.Entry<String, Object[]> not : x.entrySet()) { + remains.put(not.getKey(), not.getValue()); + } + nVm.setVmParams(remains); + nVm.setPrimaryPoolUuid(repoId); + /* to make sure stuff doesn't blow up in our face... */ + defVm = nVm; + return nVm; + } catch (Ovm3ResourceException e) { + throw e; + } + } + + /* + * get_assembly_config_xml, <class 'agent.api.hypervisor.xenxm.Xen'> + * argument: self - default: None argument: repo_id - default: None + * argument: assembly_id - default: None + */ + + /* + * import_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: assembly_id - + * default: None argument: url - default: None argument: option - default: + * None + */ + + /* + * create_assembly, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: assembly_id - + * default: None argument: templates - default: None + */ + + /* + * get_assembly_config, <class 'agent.api.hypervisor.xenxm.Xen'> argument: + * self - default: None argument: repo_id - default: None argument: + * assembly_id - default: None + */ + + /* + * unconfigure_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: params - default: None + */ + + /* + * import_template, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self + * - default: None argument: repo_id - default: None argument: template_id - + * default: None argument: url_list - default: None argument: option - + * default: None + */ + + /* + * import_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None argument: url_list - default: None argument: option - + * default: None + */ + + /* + * list_vm_core, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3Discoverer.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3Discoverer.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3Discoverer.java new file mode 100755 index 0000000..8282c1f --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3Discoverer.java @@ -0,0 +1,406 @@ +/******************************************************************************* + * 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.ovm3.resources; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.URI; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.configuration.Config; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.exception.DiscoveryException; +import com.cloud.host.Host; +import com.cloud.host.HostInfo; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.ovm3.objects.Connection; +import com.cloud.hypervisor.ovm3.objects.Linux; +import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException; +import com.cloud.resource.Discoverer; +import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.ssh.SSHCmdHelper; + +@Local(value = Discoverer.class) +public class Ovm3Discoverer extends DiscovererBase implements Discoverer, + Listener, ResourceStateAdapter { + private static final Logger LOGGER = Logger.getLogger(Ovm3Discoverer.class); + protected String publicNetworkDevice; + protected String privateNetworkDevice; + protected String guestNetworkDevice; + protected String storageNetworkDevice; + + @Inject + ClusterDao clusterDao; + @Inject + ClusterDetailsDao clusterDetailsDao; + @Inject + ResourceManager resourceMgr; + @Inject + AgentManager agentMgr; + @Inject + HostDao hostDao = null; + + protected Ovm3Discoverer() { + } + + @Override + public boolean configure(String name, Map<String, Object> params) + throws ConfigurationException { + boolean success = super.configure(name, params); + if (!success) { + return false; + } + + /* these are in Config.java */ + publicNetworkDevice = _params.get(Config.Ovm3PublicNetwork.key()); + privateNetworkDevice = _params.get(Config.Ovm3PrivateNetwork.key()); + guestNetworkDevice = _params.get(Config.Ovm3GuestNetwork.key()); + storageNetworkDevice = _params.get(Config.Ovm3StorageNetwork.key()); + resourceMgr.registerResourceStateAdapter(this.getClass() + .getSimpleName(), this); + return true; + } + + @Override + public boolean stop() { + resourceMgr.unregisterResourceStateAdapter(this.getClass() + .getSimpleName()); + return super.stop(); + } + + private boolean checkIfExisted(String guid) { + QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class); + sc.and(sc.entity().getGuid(), SearchCriteria.Op.EQ, guid); + sc.and(sc.entity().getHypervisorType(), SearchCriteria.Op.EQ, + HypervisorType.Ovm3); + List<HostVO> hosts = sc.list(); + return !hosts.isEmpty(); + } + + private boolean CheckUrl(URI url) throws DiscoveryException { + if ("http".equals(url.getScheme()) || "https".equals(url.getScheme())) { + String msg = "Discovering " + url + ": " + _params; + LOGGER.debug(msg); + } else { + String msg = "urlString is not http(s) so we're not taking care of the discovery for this: " + + url; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + return true; + } + + @Override + public Map<? extends ServerResource, Map<String, String>> find(long dcId, + Long podId, Long clusterId, URI url, String username, + String password, List<String> hostTags) throws DiscoveryException { + Connection c = null; + + CheckUrl(url); + if (clusterId == null) { + String msg = "must specify cluster Id when add host"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + if (podId == null) { + String msg = "must specify pod Id when add host"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + ClusterVO cluster = clusterDao.findById(clusterId); + if (cluster == null + || (cluster.getHypervisorType() != HypervisorType.Ovm3)) { + String msg = "invalid cluster id or cluster is not for Ovm3 hypervisors"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } else { + LOGGER.debug("cluster: " + cluster); + } + + String agentUsername = _params.get("agentusername"); + if (agentUsername == null) { + String msg = "Agent user name must be specified"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + String agentPassword = _params.get("agentpassword"); + if (agentPassword == null) { + String msg = "Agent password must be specified"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + String agentPort = _params.get("agentport"); + if (agentPort == null) { + String msg = "Agent port must be specified"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + try { + String hostname = url.getHost(); + + InetAddress ia = InetAddress.getByName(hostname); + String hostIp = ia.getHostAddress(); + String guid = UUID.nameUUIDFromBytes(hostIp.getBytes("UTF8")) + .toString(); + + if (checkIfExisted(guid)) { + String msg = "The host " + hostIp + " has been added before"; + LOGGER.info(msg); + throw new DiscoveryException(msg); + } + + LOGGER.debug("Ovm3 discover is going to disover host having guid " + + guid); + + ClusterVO clu = clusterDao.findById(clusterId); + if (clu.getGuid() == null) { + clu.setGuid(UUID.randomUUID().toString()); + } + clusterDao.update(clusterId, clu); + Map<String, String> clusterDetails = clusterDetailsDao + .findDetails(clusterId); + String ovm3vip = (clusterDetails.get("ovm3vip") == null) ? "" + : clusterDetails.get("ovm3vip"); + String ovm3pool = (clusterDetails.get("ovm3pool") == null) ? "false" + : clusterDetails.get("ovm3pool"); + String ovm3cluster = (clusterDetails.get("ovm3cluster") == null) ? "false" + : clusterDetails.get("ovm3cluster"); + + /* should perhaps only make this connect to the agent port ? */ + com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection( + hostIp, 22); + sshConnection.connect(null, 60000, 60000); + sshConnection = SSHCmdHelper.acquireAuthorizedConnection(hostIp, + username, password); + if (sshConnection == null) { + String msg = "Cannot Ssh to Ovm3 host(IP=" + hostIp + + ", username=" + username + + ", password=*******), discovery failed"; + LOGGER.warn(msg); + throw new DiscoveryException(msg); + } + + Map<String, String> details = new HashMap<String, String>(); + Ovm3HypervisorResource ovmResource = new Ovm3HypervisorResource(); + details.put("ip", hostIp); + details.put("host", hostname); + details.put("username", username); + details.put("password", password); + details.put("zone", Long.toString(dcId)); + details.put("guid", guid); + details.put("pod", Long.toString(podId)); + details.put("cluster", Long.toString(clusterId)); + details.put("agentusername", agentUsername); + details.put("agentpassword", agentPassword); + details.put("agentport", agentPort.toString()); + details.put("ovm3vip", ovm3vip); + details.put("ovm3pool", ovm3pool); + details.put("ovm3cluster", ovm3cluster); + + if (publicNetworkDevice != null) { + details.put("public.network.device", publicNetworkDevice); + } + if (privateNetworkDevice != null) { + details.put("private.network.device", privateNetworkDevice); + } + if (guestNetworkDevice != null) { + details.put("guest.network.device", guestNetworkDevice); + } + if (storageNetworkDevice != null) { + details.put("storage.network.device", storageNetworkDevice); + } + + Map<String, Object> params = new HashMap<String, Object>(); + params.putAll(details); + + ovmResource.configure(hostname, params); + ovmResource.start(); + + c = new Connection(hostIp, Integer.parseInt(agentPort), + agentUsername, agentPassword); + + /* After resource start, we are able to execute our agent api */ + Linux host = new Linux(c); + details.put("agentVersion", host.getAgentVersion()); + details.put(HostInfo.HOST_OS_KERNEL_VERSION, + host.getHostKernelRelease()); + details.put(HostInfo.HOST_OS, host.getHostOs()); + details.put(HostInfo.HOST_OS_VERSION, host.getHostOsVersion()); + details.put(HostInfo.HYPERVISOR_VERSION, + host.getHypervisorVersion()); + + Map<Ovm3HypervisorResource, Map<String, String>> resources = new HashMap<Ovm3HypervisorResource, Map<String, String>>(); + resources.put(ovmResource, details); + return resources; + } catch (UnknownHostException e) { + LOGGER.error( + "Host name resolve failed exception, Unable to discover Ovm3 host: " + + url.getHost(), e); + return null; + } catch (ConfigurationException e) { + LOGGER.error( + "Configure resource failed, Unable to discover Ovm3 host: " + + url.getHost(), e); + return null; + } catch (IOException | Ovm3ResourceException e) { + LOGGER.error("Unable to discover Ovm3 host: " + url.getHost(), e); + return null; + } + } + + @Override + public void postDiscovery(List<HostVO> hosts, long msId) + throws CloudRuntimeException { + LOGGER.debug("postDiscovery: " + hosts); + } + + @Override + public boolean matchHypervisor(String hypervisor) { + return HypervisorType.Ovm3.toString().equalsIgnoreCase(hypervisor); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.Ovm3; + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, + StartupCommand[] cmd) { + LOGGER.debug("createHostVOForConnectedAgent: " + host); + return null; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + LOGGER.debug("processAnswers: " + agentId); + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + LOGGER.debug("processCommands: " + agentId); + return false; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, + AgentControlCommand cmd) { + LOGGER.debug("processControlCommand: " + agentId); + return null; + } + + /* for reconnecting */ + @Override + public void processConnect(Host host, StartupCommand cmd, + boolean forRebalance) { + LOGGER.debug("processConnect"); + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + LOGGER.debug("processDisconnect"); + return false; + } + + @Override + public boolean isRecurring() { + return false; + } + + @Override + public int getTimeout() { + LOGGER.debug("getTimeout"); + return 0; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + LOGGER.debug("processTimeout: " + agentId); + return false; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, + StartupCommand[] startup, ServerResource resource, + Map<String, String> details, List<String> hostTags) { + LOGGER.debug("createHostVOForDirectConnectAgent: " + host); + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = (StartupRoutingCommand) firstCmd; + if (ssCmd.getHypervisorType() != HypervisorType.Ovm3) { + return null; + } + + return resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.Ovm3, + details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, + boolean isForceDeleteStorage) throws UnableDeleteHostException { + LOGGER.debug("deleteHost: " + host); + if (host.getType() != com.cloud.host.Host.Type.Routing + || host.getHypervisorType() != HypervisorType.Ovm3) { + return null; + } + + resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); + return new DeleteHostAnswer(true); + } + +}
