CLOUDSTACK-6967: Now with module! Signed-off-by: Sebastien Goasguen <runseb@gmail.com>
diff --git a/plugins/hypervisors/ovm3 b/plugins/hypervisors/ovm3 deleted file mode 160000 index bd64f2d..0000000 --- a/plugins/hypervisors/ovm3 +++ /dev/null
@@ -1 +0,0 @@ -Subproject commit bd64f2dbf461847a3f7056693bf34e80e4f7af73
diff --git a/plugins/hypervisors/ovm3/pom.xml b/plugins/hypervisors/ovm3/pom.xml new file mode 100644 index 0000000..22c9fe0 --- /dev/null +++ b/plugins/hypervisors/ovm3/pom.xml
@@ -0,0 +1,36 @@ +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>cloud-plugin-hypervisor-ovm3</artifactId> + <name>Apache CloudStack Plugin - Hypervisor OracleVM3</name> + <parent> + <groupId>org.apache.cloudstack</groupId> + <artifactId>cloudstack-plugins</artifactId> + <version>4.4.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.cloudstack</groupId> + <artifactId>xapi</artifactId> + <version>${cs.xapi.version}</version> + </dependency> + </dependencies> +</project>
diff --git a/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/module.properties b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/module.properties new file mode 100644 index 0000000..69e6469 --- /dev/null +++ b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/module.properties
@@ -0,0 +1,18 @@ +# 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. +name=ovm3-compute +parent=compute
diff --git a/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml new file mode 100644 index 0000000..42230c9 --- /dev/null +++ b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml
@@ -0,0 +1,39 @@ +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + > + + <bean id="Ovm3Fencer" class="com.cloud.hypervisor.ovm3.hypervisor.Ovm3Fencer"> + <property name="name" value="Ovm3FenceBuilder" /> + </bean> + + <bean id="Ovm3Guru" class="com.cloud.hypervisor.ovm3.hypervisor.Ovm3Guru"> + <property name="name" value="Ovm3Guru" /> + </bean> + + +</beans>
diff --git a/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/module.properties b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/module.properties new file mode 100644 index 0000000..025d4cf --- /dev/null +++ b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/module.properties
@@ -0,0 +1,18 @@ +# 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. +name=ovm3-discoverer +parent=discoverer
diff --git a/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml new file mode 100644 index 0000000..aa76271 --- /dev/null +++ b/plugins/hypervisors/ovm3/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml
@@ -0,0 +1,34 @@ +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + > + + <bean id="Ovm3Discoverer" class="com.cloud.hypervisor.ovm3.hypervisor.Ovm3Discoverer"> + <property name="name" value="Ovm3Discover" /> + </bean> + +</beans>
diff --git a/plugins/hypervisors/ovm3/scripts/clean_master.sh b/plugins/hypervisors/ovm3/scripts/clean_master.sh new file mode 100755 index 0000000..bbf1cd0 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/clean_master.sh
@@ -0,0 +1,43 @@ +#!/bin/bash +# +# 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. +# +for i in `xm list | awk '{ print $1 }' | egrep -v "Name|Domain-0"` +do + xm destroy $i +done +rm /etc/ovs-agent/db/server +rm /etc/ovs-agent/db/repository +rm /etc/ocfs2/cluster.conf +rm /nfsmnt/*/*.img +rm /nfsmnt/*/.ovspoolfs +rm /nfsmnt/*/.generic_fs_stamp +rm /OVS/Repositories/*/.generic_fs_stamp +rm /OVS/Repositories/*/.ovsrepo +/etc/init.d/ovs-agent restart +/etc/init.d/ocfs2 restart +for i in `mount | grep cs-mgmt | awk '{ print $1 }'` +do + umount $i +done +rm -rf /OVS/Repositories/* +rm -rf /nfsmnt/* +ip addr del 192.168.1.230 dev c0a80100 +ip addr del 192.168.1.161 dev c0a80100 +rm /etc/sysconfig/network-scripts/ifcfg-control0 +reboot
diff --git a/plugins/hypervisors/ovm3/scripts/clean_slave.sh b/plugins/hypervisors/ovm3/scripts/clean_slave.sh new file mode 100755 index 0000000..6d46859 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/clean_slave.sh
@@ -0,0 +1,33 @@ +#!/bin/bash +# +# 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. +# +for i in `xm list | awk '{ print $1 }' | egrep -v "Name|Domain-0"` +do + xm destroy $i +done +rm /etc/ovs-agent/db/server +rm /etc/ovs-agent/db/repository +rm /etc/ocfs2/cluster.conf +/etc/init.d/ovs-agent restart +/etc/init.d/ocfs2 restart +for i in `mount | grep cs-mgmt | awk '{ print $1 }'` +do + umount $i +done +
diff --git a/plugins/hypervisors/ovm3/scripts/create_pool_cluster.py b/plugins/hypervisors/ovm3/scripts/create_pool_cluster.py new file mode 100755 index 0000000..15c9a97 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/create_pool_cluster.py
@@ -0,0 +1,271 @@ +#!/usr/bin/python +# +# 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. +# +import os, sys, subprocess +from xml.dom.minidom import parseString + +from xmlrpclib import ServerProxy, Error + +server = ServerProxy("http://localhost:8899") + +pooledFs = 1 +normalRepo = 0 + +try: + if normalRepo: + print "normal repo" + # this litterally throws EVERYTHING away on the repo + repoDom = parseString(server.discover_repository_db()) + for node in repoDom.getElementsByTagName('Repository'): + repoUuid = node.attributes['Uuid'] + remoteMount = node.getElementsByTagName('Fs_location')[0].firstChild.nodeValue + localMount = node.getElementsByTagName('Mount_point')[0].firstChild.nodeValue + + # there is a "strong" relation between repo's and VMs + # onfortunately there is no reference in the vm.cfg + # or any known info in the configuration of the VM + # in which repo it lives.... + for dirname, dirnames, filenames in os.walk('%s/VirtualMachines/' % localMount): + for vm in dirnames: + print "Destroying vm: %s on repo %s" % (vm, repoUuid.value) + try: + mVm = server.list_vm(repoUuid.value, vm) + if mVm != None: + print server.stop_vm(repoUuid.value, vm) + print server.delete_vm(repoUuid.value, vm) + else: + print "%s already not in repo %s" % (repoUuid.value, vm) + except Error, v: + print "Unable to destroy: %s" % (v) + continue + + # VMs = server.list_vms() + # for vm in VMs: + # if vm['domid'] != '0': + # print vm + # print server.delete_vm(repoUuid.value, vm['uuid']) + + rc = server.delete_repository(repoUuid.value, True) + # Set to false if you want to keep data: ^^^^ + print "Repository: %s" % repoUuid.value + if (rc == None): + print "Ok repo: %s destroyed!" % repoUuid.value + # now unmount the FS + # print server.unmount_repository_fs(localMount) + else: + print "Failed repo: %s not destroyed!" % repoUuid.value + + # for now only treat NFS stuff as we're testing with that.. + nfsHost='cs-mgmt' + nfsDom = server.storage_plugin_listMountPoints( + 'oracle.generic.NFSPlugin.GenericNFSPlugin', + { 'status': '', + 'admin_user': '', + 'admin_host': '', + 'uuid': '', + 'total_sz': 0, + 'admin_passwd': '', + 'free_sz': 0, + 'name': '', + 'access_host': nfsHost, + 'storage_type': 'FileSys', + 'alloc_sz': 0, + 'access_grps': [], + 'used_sz': 0, + 'storage_desc': '' + }) + for node in nfsDom: + props = {'status': node['status'], + 'uuid': '', + 'access_host': nfsHost, + 'storage_type': 'FileSys', + 'name': '' } + extprops = {'status': node['status'], + 'uuid': node['fs_uuid'], + 'ss_uuid': '', + 'size': 0, + 'free_sz': '', + 'state': 1, + 'access_grp_names': [], + 'access_path': nfsHost + ':' + '/volumes/cs-data/secondary', + 'name': ''} + # rc = server.storage_plugin_unmount('oracle.generic.NFSPlugin.GenericNFSPlugin', props, extprops, nfsMnt, True) + # print rc + + nfsDom = parseString(server.discover_mounted_file_systems('nfs')) + for node in nfsDom.getElementsByTagName('Mount'): + nfsMnt = node.attributes['Dir'].value + print 'Mountpoint: %s' % (nfsMnt) + fsStamp = '%s/.generic_fs_stamp' % nfsMnt + # remove this so we don't cock up next run + if os.path.isfile(fsStamp): + print "Stamp found: %s" % fsStamp + os.unlink(fsStamp) + + rc = server.storage_plugin_unmount('oracle.generic.NFSPlugin.GenericNFSPlugin', props, extprops, nfsMnt, True) + print rc + + + if pooledFs: + print "pooling" + # pool stuff + poolalias="ItsMyPool" + poolmvip="192.168.1.161" + poolfirsthost = { + 'ip': "192.168.1.64", + 'hn': "ovm-1", + 'id': 0, + 'role': 'utility,xen' + } + fstype="nfs" + fstarget="cs-mgmt:/volumes/cs-data/primary" + poolid="0004fb0000020000ba9aaf00ae5e2d73" + clusterid="ba9aaf00ae5e2d72" + poolfsuuid="0004fb0000050000e70fbddeb802208f" + poolfsnfsbaseuuid="b8ca41cb-3469-4f74-a086-dddffe37dc2d" + manageruuid="0004fb00000100000af70d20dcce7d65" + pooluuid="0004fb0000020000ba9aaf00ae5e2d73" + blocksize="" + clustersize="" + journalesize="" + + # o2cb is the problem.... /etc/init.d/o2cb + # sets it's config in /etc/sysconfig/o2cb (can be removed) + # dmsetup requires the stopping of o2cb first, + # then the removal of the config, after which dmsetup + # can remove the device from /dev/mapper/ + # eventually cluster cleanup can be done by removing + # stuff from /etc/ovs-agent/db + # also clean /etc/ocfs2/cluster.conf + print server.create_pool_filesystem( + fstype, + fstarget, + clusterid, + poolfsuuid, + poolfsnfsbaseuuid, + manageruuid, + pooluuid + ) + + # poolDom = server.discover_server_pool() + # print poolDom + # poolDom = parseString(server.discover_server_pool()) + # if poolDom.getElementsByTagName('Server_Pool'): + # get unique id + cluster = server.is_cluster_online() + if cluster == True: + print "clean up pool" + # print server.destroy_cluster(poolfsuuid) + # deconfigure cluster + # print server.destroy_server_pool(poolid) + + if cluster == False: + print "create_server_pool" + # first take ownership. without an owner nothing happens + print server.take_ownership(manageruuid, "") + # we need to add the first host first to the pool.... + poolDom = server.discover_server_pool() + print poolDom + poolDom = parseString(server.discover_server_pool()) + if poolDom.getElementsByTagName('Server_Pool'): + print server.destroy_server_pool(pooluuid) + + print server.create_pool_filesystem( + fstype, + fstarget, + clusterid, + poolfsuuid, + poolfsnfsbaseuuid, + manageruuid, + pooluuid + ) + print server.create_server_pool(poolalias, + pooluuid, + poolmvip, + poolfirsthost['id'], + poolfirsthost['hn'], + poolfirsthost['ip'], + poolfirsthost['role']) + + print "configure_virtual_ip" + server.configure_virtual_ip(poolmvip, poolfirsthost['ip']) + server.set_pool_member_ip_list(['192.168.1.64','192.168.1.65'],) + print "configure for cluster" + server.configure_server_for_cluster( + { + 'O2CB_HEARTBEAT_THRESHOLD': '61', + 'O2CB_RECONNECT_DELAY_MS': '2000', + 'O2CB_KEEPALIVE_DELAY_MS': '2000', + 'O2CB_BOOTCLUSTER': clusterid, + 'O2CB_IDLE_TIMEOUT_MS': '60000', + 'O2CB_ENABLED': 'true', + 'O2CB_STACK': 'o2cb' + }, + { + 'node': [ + { + 'ip_port': 7777, + 'cluster': clusterid, + 'ip_address': poolfirsthost['ip'], + 'name': poolfirsthost['hn'], + 'number': poolfirsthost['id'] + } + ], + 'heartbeat': [ + { + 'cluster': clusterid, + # uppercase poolfsuuid + 'region': '0004FB0000050000E70FBDDEB802208F' + } + ], + 'cluster': [ + { + 'heartbeat_mode': 'global', + 'node_count': 1, + 'name': clusterid + } + ] + }, + 'nfs', + 'cs-mgmt:/volumes/cs-data/primary', + poolfsuuid, + poolfsnfsbaseuuid + ) + print "create cluster" + server.create_cluster(poolfsuuid,) + + poolDom = parseString(server.discover_server_pool()) + for node in poolDom.getElementsByTagName('Server_Pool'): + id = node.getElementsByTagName('Unique_Id')[0].firstChild.nodeValue + alias = node.getElementsByTagName('Pool_Alias')[0].firstChild.nodeValue + mvip = node.getElementsByTagName('Master_Virtual_Ip')[0].firstChild.nodeValue + print "pool: %s, %s, %s" % (id, mvip, alias) + members = node.getElementsByTagName('Member') + for member in members: + mip = member.getElementsByTagName('Registered_IP')[0].firstChild.nodeValue + print "member: %s" % (mip) + + print server.is_cluster_online() + print server.discover_cluster() + print server.discover_pool_filesystem() + print server.discover_server_pool() + # server.destroy_server_pool(pooluuid) + +except Error, v: + print "ERROR", v
diff --git a/plugins/hypervisors/ovm3/scripts/info.py b/plugins/hypervisors/ovm3/scripts/info.py new file mode 100755 index 0000000..518aaf1 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/info.py
@@ -0,0 +1,111 @@ +#!/usr/bin/python +# +# 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. +# +import os, sys, subprocess, socket,fcntl, struct +from socket import gethostname +import errno +from socket import error as socket_error +from xml.dom.minidom import parseString + +from xmlrpclib import ServerProxy, Error + +def spCon(proto, auth, host, port): + print "trying %s on %s@%s:%s" % (proto, auth, host, port) + try: + x=ServerProxy("%s://%s@%s:%s" % (proto, auth, host, port)) + x.echo(proto) + return x + except Error, v: + return + except socket_error, serr: + return + +def getCon(auth, host, port): + try: + server = spCon("http", auth, host, port) + if server: + return server + else: + server = spCon("https", auth, host, port) + except Error, v: + print "ERROR", v + return server + +def get_ip_address(ifname): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return socket.inet_ntoa(fcntl.ioctl( + s.fileno(), + 0x8915, # SIOCGIFADDR + struct.pack('256s', ifname[:15]) + )[20:24]) + +def is_it_up(host, port): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + s.connect((host, port)) + s.close() + except: + print "host: %s:%s DOWN" % (host, port) + return False + + print "host: %s:%s UP" % (host, port) + return True + +# hmm master actions don't apply to a slave +master="192.168.1.161" +port=8899 +user = "oracle" +password = "test123" +auth = "%s:%s" % (user, password) +server = getCon(auth, 'localhost', port) +mserver = getCon(auth, master, port) +poolNode=True +interface = "c0a80100" +role='xen,utility' +hostname=gethostname() +ip = get_ip_address(interface) +poolMembers = [] +xserver = server +poolCount = 0 + +try: + print server.discover_pool_filesystem() + print + print server.discover_server_pool() + poolDom = parseString(server.discover_server_pool()) + for node in poolDom.getElementsByTagName('Server_Pool'): + id = node.getElementsByTagName('Unique_Id')[0].firstChild.nodeValue + alias = node.getElementsByTagName('Pool_Alias')[0].firstChild.nodeValue + mvip = node.getElementsByTagName('Master_Virtual_Ip')[0].firstChild.nodeValue + print "pool: %s, %s, %s" % (id, mvip, alias) + members = node.getElementsByTagName('Member') + for member in members: + poolCount = poolCount + 1 + mip = member.getElementsByTagName('Registered_IP')[0].firstChild.nodeValue + print "member: %s" % (mip) + if mip == ip: + pooled = True + else: + poolMembers.append(mip) + + # print server.discover_server() + +except Error, v: + print "ERROR", v
diff --git a/plugins/hypervisors/ovm3/scripts/ovs_agent_plugin/cloudstack.py b/plugins/hypervisors/ovm3/scripts/ovs_agent_plugin/cloudstack.py new file mode 100644 index 0000000..f655760 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/ovs_agent_plugin/cloudstack.py
@@ -0,0 +1,344 @@ +#!/usr/bin/python +# +# 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. +# +import logging +import time +import re +import os.path +import paramiko +import subprocess +import socket + +from xen.util.xmlrpcclient import ServerProxy +from xmlrpclib import Error +from xen.xend import XendClient +from agent.api.base import Agent +from agent.lib.settings import get_api_version +from xen.xend import sxp + +class CloudStack(Agent): + """ + Cloudstack plugin for OVM3.2.x. + """ + + # exposed services + def get_services(self, version=None): + return { + 'call': call, + 'get_vncport': getVncPort, + 'exec_domr': domrExec, + 'check_domr_port': domrCheckPort, + 'check_domr_ssh': domrCheckSsh, + 'ovs_control_interface': ovsControlInterface, + 'ovs_mkdir': ovsMkdir, + 'ovs_check_file': ovsCheckFile, + 'ovs_upload_ssh_key': ovsUploadSshKey, + 'ovs_dom0_stats': ovsDom0Stats, + 'ovs_domU_stats': ovsDomUStats, + 'get_module_version': getModuleVersion, + 'ping': ping, +# 'ovs_agent_set_ssl': ovsAgentSetSsl, +# 'ovs_agent_set_port': ovsAgentSetPort, +# 'ovs_restart_agent': ovsRestartAgent, + } + + def getName(self): + return self.__class__.__name__ + +# which version are we intended for? +def getModuleVersion(): + return "0.1" + +# call test +def call(msg): + return msg + +# execute something on domr +def domrExec(ip, cmd, timeout=10, username="root", port=3922, keyfile="~/.ssh/id_rsa.cloud"): + ssh = paramiko.SSHClient() + ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + privatekeyfile = os.path.expanduser(keyfile) + key = paramiko.RSAKey.from_private_key_file(privatekeyfile) + ssh.connect(ip, port, username, pkey=key, timeout=timeout) + ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmd) + exit_status = ssh_stdout.channel.recv_exit_status() + ssh.close() + return { "rc": exit_status, + "out": ''.join(ssh_stdout.readlines()), + "err": ''.join(ssh_stderr.readlines()) }; + +# check a port on domr +def domrPort(ip, port=3922, timeout=3): + return domrCheckPort(ip, port, timeout=timeout) + +# check a port on domr +def domrCheckPort(ip, port=3922, timeout=3): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + s.connect((ip, port)) + s.close() + return True + except: + return False + +# check ssh +def domrCheckSsh(ip, port=3922, timeout=10): + x = domrExec(ip, "", port=port, timeout=timeout) + if (x.get("rc") == 0): + return True + return False + +def _ovsIni(setting, set): + ini="/etc/ovs-agent/agent.ini" + replaced=False + if os.path.isfile(ini): + import fileinput + for line in fileinput.FileInput(ini, inplace=1): + line=line.rstrip('\n') + if re.search("%s=" % setting, line): + line="%s=%s" % (setting, set) + replaced=True + print line + return replaced + +# enable/disable ssl for the agent +def ovsAgentSetSsl(state): + ena="disable" + if state and state != "disable" and state.lower() != "false": + ena="enable" + return _ovsIni("ssl", ena) + +def ovsAgentSetPort(port): + return _ovsIni("port", port) + +def ovsRestartAgent(): + return restartService("ovs-agent") + +# replace with popen +def restartService(service): + command = ['service', service, 'restart']; + subprocess.call(command, shell=False) + return True + +# sets the control interface and removes the route net entry +def ovsControlInterface(dev, ipmask): + command = ['route', 'del', '-net', ipmask]; + subprocess.call(command, shell=False) + command = ['ifconfig', dev, 'arp'] + subprocess.call(command, shell=False) + return True + +# create a dir if we need it +def ovsMkdir(dir, mode=0700): + if not os.path.exists(dir): + return os.makedirs(dir, mode) + return True + +# if a file exists, easy +def ovsCheckFile(file): + if os.path.isfile(file): + return True + return False + +# upload keys +def ovsUploadSshKey(keyfile, content): + keydir=os.path.expanduser("~/.ssh") + key="%s/%s" % (keydir, keyfile) + try: + ovsMkdir(os.path.expanduser(keydir)) + except Error, v: + print "was already there %s" % keydir + + try: + text_file = open("%s" % key, "w") + text_file.write("%s" % content) + text_file.close() + except Error, v: + print "something went wrong %s" % v + return False + return True + + +# older python, +def ovsDom0Stats(bridge): + stats={} + stats['cpu'] = "%s" % (100 - float(os.popen("top -b -n 1 | grep Cpu\(s\): | cut -d% -f4|cut -d, -f2").read())) + stats['free'] = "%s" % (1048576 * int(os.popen("xm info | grep free_memory | awk '{ print $3 }'").read())) + stats['total'] = "%s" % (1048576 * int(os.popen("xm info | grep total_memory | awk '{ print $3 }'").read())) + stats['tx'] = os.popen("netstat -in | grep %s | head -1 | awk '{print $4 }'" % bridge).read() + stats['rx'] = os.popen("netstat -in | grep %s | head -1 | awk '{print $8 }'" % bridge).read() + return stats + +def getVncPort(domain): + port = "0" + if re.search("\w-(\d+-)?\d+-VM", domain): + server=ServerProxy(XendClient.uri) + dom=server.xend.domain(domain, 1) + devices = [child for child in sxp.children(dom) + if len(child) > 0 and child[0] == "device"] + vfbs_sxp = map(lambda x: x[1], [device for device in devices + if device[1][0] == "vfb"])[0] + loc=[child for child in vfbs_sxp + if child[0] == "location"][0][1] + listner, port = loc.split(":") + else: + print "no valid domain: %s" % domain + return port + +def get_child_by_name(exp, childname, default = None): + try: + return [child for child in sxp.children(exp) + if child[0] == childname][0][1] + except: + return default + +def ovsDomUStats(domain): + _rd_bytes=0 + _wr_bytes=0 + _rd_ops=0 + _wr_ops=0 + _tx_bytes=0 + _rx_bytes=0 + stats={} + server=ServerProxy(XendClient.uri) + dominfo=server.xend.domain(domain, 1) + domid=get_child_by_name(dominfo, "domid") + + # vbds + devs = server.xend.domain.getDeviceSxprs(domain, 'vbd') + devids = [dev[0] for dev in devs] + for dev in devids: + sys_path="/sys/devices/%s-%s-%s/statistics" % ("vbd", domid, dev) + _rd_bytes += long(open("%s/rd_sect" % sys_path).readline().strip()) + _wr_bytes += long(open("%s/wr_sect" % sys_path).readline().strip()) + _rd_ops += long(open("%s/rd_req" % sys_path).readline().strip()) + _wr_ops += long(open("%s/wr_req" % sys_path).readline().strip()) + + # vifs + devs = server.xend.domain.getDeviceSxprs(domain, 'vif') + devids = [dev[0] for dev in devs] + for dev in devids: + vif="vif%s.%s" % (domid, dev) + sys_path="/sys/devices/%s-%s-%s/net/%s/statistics" % ("vif", domid, dev, vif) + _tx_bytes += long(open("%s/tx_bytes" % sys_path).readline().strip()) + _rx_bytes += long(open("%s/rx_bytes" % sys_path).readline().strip()) + + epoch=time.time() + stats['rd_bytes'] = "%s" % (_rd_bytes * 512) + stats['wr_bytes'] = "%s" % (_wr_bytes * 512) + stats['rd_ops'] = "%s" % (_rd_ops) + stats['wr_ops'] = "%s" % (_wr_ops) + stats['tx_bytes'] = "%s" % (_tx_bytes) + stats['rx_bytes'] = "%s" % (_rx_bytes) + stats['cputime']= "%s" % get_child_by_name(dominfo, "cpu_time") + stats['uptime']= "%s" % (epoch - get_child_by_name(dominfo, "start_time")) + stats['vcpus']= "%s" % get_child_by_name(dominfo, "online_vcpus") + return stats + +def ping(host, count=3): + if os.system("ping -c %s %s " % (count, host)) == 0: + return True + return False + +# add SystemVM stuff here.... +# + +# +# Self deploy and integration, not de-integration +# should return False if fails +# +# install us if we are missing in: +# /usr/lib64/python2.4/site-packages/agent/api +# and add our hooks in: +# /usr/lib64/python2.4/site-packages/agent/target/api.py +if __name__ == '__main__': + from distutils.sysconfig import get_python_lib + from agent.target.api import MODULES + from shutil import copyfile + import inspect, os, hashlib, getopt, sys + + # default vars + exist=False + agentpath="%s/agent" % (get_python_lib(1)) + api="%s/target/api.py" % (agentpath) + modpath="%s/api" % (agentpath) + ssl="disable" + port=0 + + # get options + try: + opts, args = getopt.getopt(sys.argv[1:], "sp::", + [ 'port=','ssl=']) + except getopt.GetoptError: + print "Available Options: --port=, --ssl=" + sys.exit() + + for o, a in opts: + if o in ('-s', '--ssl'): + ssl = a + if o in ('-p', '--port'): + port = int(a) + + # check if we're in the modules already + cs = CloudStack() + for mod in MODULES: + if re.search(cs.getName(), "%s" % (mod)): + exist=True + + # if we're not: + if not exist: + if os.path.isfile(api): + import fileinput + for line in fileinput.FileInput(api, inplace=1): + line=line.rstrip('\n') + if re.search("import common", line): + line="%s, cloudstack" % (line) + if re.search("MODULES", line): + n=cs.getName() + line="%s\n\t%s.%s," % (line, n.lower(), n) + print line + print "Api inserted, %s in %s" % (cs.getName(), api) + else: + print "Api missing, %s" % (api) + else: + print "Api present, %s in %s" % (cs.getName(), api) + + # either way check our version and install if checksum differs + modfile="%s/%s.py" % (modpath, cs.getName().lower()) + me=os.path.abspath(__file__) + if os.path.isfile(modfile): + if hashlib.md5(open(me).read()).hexdigest() != hashlib.md5(open(modfile).read()).hexdigest(): + print "Module copy, %s" % (modfile) + copyfile(me, modfile) + else: + print "Module correct, %s" % (modfile) + else: + print "Module copy, %s" % (modfile) + copyfile(me, modfile) + + # setup ssl and port + if ssl: + ovsAgentSetSsl(ssl) + if port > 1024: + ovsAgentSetPort(port) + + # restart either way + ovsRestartAgent()
diff --git a/plugins/hypervisors/ovm3/scripts/password.py b/plugins/hypervisors/ovm3/scripts/password.py new file mode 100755 index 0000000..25404a9 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/password.py
@@ -0,0 +1,57 @@ +#!/usr/bin/python +# +# 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. +# +import os, sys, subprocess, socket,fcntl, struct +from socket import gethostname +from xml.dom.minidom import parseString + +from xmlrpclib import ServerProxy, Error + +def spCon(proto, host, port): + print "trying %s on %s:%s" % (proto, host, port) + try: + x=ServerProxy("%s://%s:%s" % (proto, host, port)) + x.echo(proto) + return x + except Error, v: + print "ERROR", v + return + +def getCon(host, port): + try: + server = spCon("http", host, port) + except Error, v: + print "ERROR", v + server = spCon("https", host, port) + + return server + +# hmm master actions don't apply to a slave +port=8899 +user = "oracle" +password = "test123" +auth = "%s:%s" % (user, password) +host = "localhost" + +print "setting up password" +try: + con = getCon(host, port) + print con.update_agent_password(user, password) +except Error, v: + print "ERROR", v
diff --git a/plugins/hypervisors/ovm3/scripts/repo_pool.py b/plugins/hypervisors/ovm3/scripts/repo_pool.py new file mode 100755 index 0000000..71feca8 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/repo_pool.py
@@ -0,0 +1,186 @@ +#!/usr/bin/python +# +# 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. +# +import os, sys, subprocess, socket,fcntl, struct +from socket import gethostname +from xml.dom.minidom import parseString + +from xmlrpclib import ServerProxy, Error + +def get_ip_address(ifname): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return socket.inet_ntoa(fcntl.ioctl( + s.fileno(), + 0x8915, # SIOCGIFADDR + struct.pack('256s', ifname[:15]) + )[20:24]) + +def is_it_up(host, port): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + s.connect((host, port)) + s.close() + except: + print "host: %s:%s DOWN" % (host, port) + return False + + print "host: %s:%s UP" % (host, port) + return True + +# hmm master actions don't apply to a slave +master="192.168.1.161" +port=8899 +user = "oracle" +password = "*******" +auth = "%s:%s" % (user, password) +server = ServerProxy("http://%s:%s" % ("localhost", port)) +mserver = ServerProxy("http://%s@%s:%s" % (auth, master, port)) +poolNode=True +interface = "c0a80100" +role='xen,utility' +hostname=gethostname() +ip = get_ip_address(interface) +poolMembers = [] +xserver = server + +print "setting up password" +server.update_agent_password(user, password) + +if (is_it_up(master, port)): + print "master seems to be up, slaving" + xserver = mserver +else: + print "no master yet, will become master" + +# other mechanism must be used to make interfaces equal... +try: + # pooling related same as primary storage! + poolalias="Pool 0" + poolid="0004fb0000020000ba9aaf00ae5e2d73" + poolfsnfsbaseuuid="7718562d-872f-47a7-b454-8f9cac4ffa3a" + pooluuid=poolid + poolfsuuid=poolid + clusterid="ba9aaf00ae5e2d72" + mgr="d1a749d4295041fb99854f52ea4dea97" + poolmvip=master + + poolfsnfsbaseuuid="6824e646-5908-48c9-ba44-bb1a8a778084" + repoid="6824e646590848c9ba44bb1a8a778084" + poolid=repoid + repo="/OVS/Repositories/%s" % (repoid) + repomount="cs-mgmt:/volumes/cs-data/secondary" + + # primary + primuuid="7718562d872f47a7b4548f9cac4ffa3a" + ssuuid="7718562d-872f-47a7-b454-8f9cac4ffa3a" + fshost="cs-mgmt" + fstarget="/volumes/cs-data/primary" + fstype="nfs" + fsname="Primary storage" + fsmntpoint="%s:%s" % (fshost, fstarget) + fsmnt="/nfsmnt/%s" % (ssuuid) + fsplugin="oracle.generic.NFSPlugin.GenericNFSPlugin" + + # set the basics we require to "operate" + print server.take_ownership(mgr, '') + print server.update_server_roles(role,) + + # if we're pooling pool... + if (poolNode == True): + poolCount = 0 + pooled = False + + # check pooling + try: + poolDom = parseString(xserver.discover_server_pool()) + print xserver.discover_server_pool() + for node in poolDom.getElementsByTagName('Server_Pool'): + id = node.getElementsByTagName('Unique_Id')[0].firstChild.nodeValue + alias = node.getElementsByTagName('Pool_Alias')[0].firstChild.nodeValue + mvip = node.getElementsByTagName('Master_Virtual_Ip')[0].firstChild.nodeValue + print "pool: %s, %s, %s" % (id, mvip, alias) + members = node.getElementsByTagName('Member') + for member in members: + poolCount = poolCount + 1 + mip = member.getElementsByTagName('Registered_IP')[0].firstChild.nodeValue + print "member: %s" % (mip) + if mip == ip: + pooled = True + else: + poolMembers.append(mip) + + except Error,v: + print "no master will become master, %s" % v + + if (pooled == False): + # setup the repository + print "setup repo" + print server.mount_repository_fs(repomount, repo) + try: + print "adding repo" + print server.add_repository(repomount, repo) + except Error, v: + print "will create the repo, as it's not there", v + print server.create_repository(repomount, repo, repoid, "repo") + + print "not pooled!" + if (poolCount == 0): + print "no pool yet, create it" + # check if a pool exists already if not create + # pool if so add us to the pool + print "create pool fs" + print server.create_pool_filesystem( + fstype, + "%s/VirtualMachines/" % repomount, + clusterid, + poolfsuuid, + poolfsnfsbaseuuid, + mgr, + pooluuid + ) + print "create pool" + print server.create_server_pool(poolalias, + pooluuid, + poolmvip, + poolCount, + hostname, + ip, + role + ) + else: + print "join the pool" + print server.join_server_pool(poolalias, + pooluuid, + poolmvip, + poolCount, + hostname, + ip, + role + ) + + # add member to ip list ? + poolMembers.append(ip) + print "mambers for pool: %s" % poolMembers + print xserver.set_pool_member_ip_list(poolMembers) + + print server.discover_server_pool() + +except Error, v: + print "ERROR", v
diff --git a/plugins/hypervisors/ovm3/scripts/simple_pool.py b/plugins/hypervisors/ovm3/scripts/simple_pool.py new file mode 100755 index 0000000..756de93 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/simple_pool.py
@@ -0,0 +1,209 @@ +#!/usr/bin/python +# +# 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. +# +import os, sys, subprocess, socket,fcntl, struct +from socket import gethostname +from xml.dom.minidom import parseString +import errno +from socket import error as socket_error + +from xmlrpclib import ServerProxy, Error + +def spCon(proto, auth, host, port): + print "trying %s on %s@%s:%s" % (proto, auth, host, port) + try: + x=ServerProxy("%s://%s@%s:%s" % (proto, auth, host, port)) + x.echo(proto) + return x + except Error, v: + return + except socket_error, serr: + return + +def getCon(auth, host, port): + try: + server = spCon("http", auth, host, port) + if server: + return server + else: + server = spCon("https", auth, host, port) + except Error, v: + print "ERROR", v + return server + +def get_ip_address(ifname): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return socket.inet_ntoa(fcntl.ioctl( + s.fileno(), + 0x8915, # SIOCGIFADDR + struct.pack('256s', ifname[:15]) + )[20:24]) + +# hmm master actions don't apply to a slave +master="192.168.1.161" +port=8899 +passw='test123' +user='oracle' +auth="%s:%s" % (user, passw) +server = getCon(auth, "localhost", port) +mserver = getCon(auth, master, port) +try: + mserver.echo("test") +except AttributeError, v: + print "no mserver, becoming mserver" + mserver=server + +poolNode=True +interface = "c0a80100" +role='xen,utility' +hostname=gethostname() +ip = get_ip_address(interface) +nodes=[] + +try: + # pooling related same as primary storage! + poolalias="Pool 0" + clusterid="ba9aaf00ae5e2d72" + mgr="d1a749d4295041fb99854f52ea4dea97" + poolmvip=master + + # primary + primuuid="7718562d872f47a7b4548f9cac4ffa3a" + ssuuid="7718562d-872f-47a7-b454-8f9cac4ffa3a" + fshost="cs-mgmt" + fstarget="/volumes/cs-data/primary/ovm" + fstype="nfs" + fsname="Primary storage" + fsmntpoint="%s:%s" % (fshost, fstarget) + fsmntpoint2="%s:%s" % (fshost, "/volumes/cs-data/secondary") + fsmntpoint="%s/VirtualMachines" % (fsmntpoint2) + fsmnt="/nfsmnt/%s" % (ssuuid) + fsplugin="oracle.generic.NFSPlugin.GenericNFSPlugin" + repo="/OVS/Repositories/%s" % (primuuid) + + # set the basics we require to "operate" + print server.take_ownership(mgr, '') + print server.update_server_roles(role,) + + # setup the repository + print server.mount_repository_fs(fsmntpoint2, repo) + try: + print server.add_repository(fsmntpoint2, repo) + except Error, v: + print "will create the repo, as it's not there", v + print server.create_repository(fsmntpoint2, repo, primuuid, "A repository") + + # if we're pooling pool... + if (poolNode == True): + poolCount = 0 + pooled = False + + # check pooling + poolDom = parseString(mserver.discover_server_pool()) + for node in poolDom.getElementsByTagName('Server_Pool'): + id = node.getElementsByTagName('Unique_Id')[0].firstChild.nodeValue + alias = node.getElementsByTagName('Pool_Alias')[0].firstChild.nodeValue + mvip = node.getElementsByTagName('Master_Virtual_Ip')[0].firstChild.nodeValue + print "pool: %s, %s, %s" % (id, mvip, alias) + members = node.getElementsByTagName('Member') + for member in members: + poolCount = poolCount + 1 + mip = member.getElementsByTagName('Registered_IP')[0].firstChild.nodeValue + if (mip == ip): + pooled = True + else: + nodes.append(mip) + print "member: %s" % (mip) + + # if (pooled == False): + try: + if (poolCount == 0): + print "master" + # check if a pool exists already if not create + # pool if so add us to the pool + print server.configure_virtual_ip(master, ip) + print server.create_pool_filesystem( + fstype, + fsmntpoint, + clusterid, + primuuid, + ssuuid, + mgr, + primuuid + ) + print server.create_server_pool(poolalias, + primuuid, + poolmvip, + poolCount, + hostname, + ip, + role + ) + else: + try: + print "slave" + print server.join_server_pool(poolalias, + primuuid, + poolmvip, + poolCount, + hostname, + ip, + role + ) + except Error, v: + print "host already part of pool?: %s" % (v) + + nodes.append(ip) + for node in nodes: + # con = getCon(auth, node, port) + # print con.set_pool_member_ip_list(nodes); + print mserver.dispatch("http://%s@%s:%s/api/3" % (auth, node, port), "set_pool_member_ip_list", nodes) + # print server.configure_virtual_ip(master, ip) + except Error, e: + print "something went wrong: %s" % (e) + + # sys.exit() + # mount the primary fs + print server.storage_plugin_mount( + fsplugin, + { + 'uuid': primuuid, + 'storage_desc': fsname, + 'access_host': fshost, + 'storage_type': 'FileSys', + 'name':primuuid + }, + { + 'status': '', + 'uuid': ssuuid, + 'ss_uuid': primuuid, + 'size': 0, + 'state': 1, + 'access_grp_names': [], + 'access_path': fsmntpoint, + 'name': fsname + }, + fsmnt, + '', + True, + [] + ) + +except Error, v: + print "ERROR", v
diff --git a/plugins/hypervisors/ovm3/scripts/socat.sh b/plugins/hypervisors/ovm3/scripts/socat.sh new file mode 100755 index 0000000..c3fbc44 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/socat.sh
@@ -0,0 +1,2 @@ +CERT="/etc/ovs-agent/cert" +socat OPENSSL-LISTEN:8899,reuseaddr,fork,verify=0,key=$CERT/key.pem,cert=$CERT/certificate.pem TCP:localhost:8898 &
diff --git a/plugins/hypervisors/ovm3/scripts/tail.sh b/plugins/hypervisors/ovm3/scripts/tail.sh new file mode 100755 index 0000000..fe88bc0 --- /dev/null +++ b/plugins/hypervisors/ovm3/scripts/tail.sh
@@ -0,0 +1,2 @@ +cd /var/log +tail -f ovm-consoled.log devmon.log messages ovs-agent.log ovmwatch.log
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/ha/Ovm3Investigator.java b/plugins/hypervisors/ovm3/src/com/cloud/ha/Ovm3Investigator.java new file mode 100644 index 0000000..980fa1f --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/ha/Ovm3Investigator.java
@@ -0,0 +1,81 @@ +/* + * 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.ha; + +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckOnHostCommand; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.AdapterBase; + +@Local(value = Investigator.class) +public class Ovm3Investigator extends AdapterBase implements Investigator { + private final static Logger s_logger = Logger.getLogger(Ovm3Investigator.class); + @Inject + HostDao _hostDao; + @Inject + AgentManager _agentMgr; + @Inject + ResourceManager _resourceMgr; + + @Override + public Boolean isVmAlive(com.cloud.vm.VirtualMachine vm, Host host) { + Status status = isAgentAlive(host); + if (status == null) { + return null; + } + return status == Status.Up ? true : null; + } + + @Override + public Status isAgentAlive(Host agent) { + if (agent.getHypervisorType() != Hypervisor.HypervisorType.Ovm3) { + return null; + } + CheckOnHostCommand cmd = new CheckOnHostCommand(agent); + List<HostVO> neighbors = _resourceMgr.listHostsInClusterByStatus(agent.getClusterId(), Status.Up); + for (HostVO neighbor : neighbors) { + if (neighbor.getId() == agent.getId() || neighbor.getHypervisorType() != Hypervisor.HypervisorType.Ovm3) { + continue; + } + try { + Answer answer = _agentMgr.easySend(neighbor.getId(), cmd); + if (answer != null) { + return answer.getResult() ? Status.Down : Status.Up; + } + } catch (Exception e) { + s_logger.debug("Failed to send command to host: " + neighbor.getId()); + } + } + + return null; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Discoverer.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Discoverer.java new file mode 100755 index 0000000..bd1d90d --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Discoverer.java
@@ -0,0 +1,411 @@ +// 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.hypervisor; + +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 org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.Listener; +import com.cloud.agent.AgentManager; +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.host.Status; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.configuration.Config; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.ClusterDetailsDao; +// import com.cloud.exception.DiscoveryException; +import com.cloud.host.HostInfo; +import com.cloud.host.HostVO; +import com.cloud.host.Host; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.ovm3.object.Linux; +import com.cloud.hypervisor.ovm3.object.Connection; +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 s_logger = Logger + .getLogger(Ovm3Discoverer.class); + protected String _publicNetworkDevice; + protected String _privateNetworkDevice; + protected String _guestNetworkDevice; + protected String _storageNetworkDevice; + private String _ovsAgentPath = "/etc/ovs-agent/agent.ini"; + + @Inject + ClusterDao _clusterDao; + @Inject + ClusterDetailsDao _clusterDetailsDao; + @Inject + ResourceManager _resourceMgr; + @Inject + AgentManager _agentMgr; + @Inject + HostDao _hostDao = null; + + @Override + public boolean configure(String name, Map<String, Object> params) + throws ConfigurationException { + super.configure(name, params); + /* 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; + } + + protected Ovm3Discoverer() { + } + + @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(); + } + + @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 CloudRuntimeException { + Connection c = null; + + if (url.getScheme().equals("http") || url.getScheme().equals("https")) { + String msg = "Discovering " + url + + ": " + _params; + s_logger.debug(msg); + } else { + String msg = "urlString is not http(s) so we're not taking care of the discovery for this: " + + url; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + + if (clusterId == null) { + String msg = "must specify cluster Id when add host"; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + + if (podId == null) { + String msg = "must specify pod Id when add host"; + s_logger.debug(msg); + throw new CloudRuntimeException(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"; + s_logger.info(msg); + throw new CloudRuntimeException(msg); + } else { + s_logger.info("cluster: " + cluster); + } + + String agentUsername = _params.get("agentusername"); + if (agentUsername == null) { + String msg = "Agent user name must be specified"; + s_logger.info(msg); + throw new CloudRuntimeException(msg); + } + + String agentPassword = _params.get("agentpassword"); + if (agentPassword == null) { + String msg = "Agent password must be specified"; + s_logger.info(msg); + throw new CloudRuntimeException(msg); + } + + String agentPort = _params.get("agentport"); + if (agentPort == null) { + String msg = "Agent port must be specified"; + s_logger.info(msg); + throw new CloudRuntimeException(msg); + } + + try { + String hostname = url.getHost(); + /* port = url.getPort(); */ + + InetAddress ia = InetAddress.getByName(hostname); + String hostIp = ia.getHostAddress(); + String guid = UUID.nameUUIDFromBytes(hostIp.getBytes()).toString(); + + if (checkIfExisted(guid)) { + String msg = "The host " + hostIp + " has been added before"; + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + + s_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 = String.format("Cannot connect to Ovm3 host(IP=%1$s, username=%2$s, password=*******), discovery failed", + hostIp, username); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + + Map<String, String> details = new HashMap<String, String>(); + Ovm3ResourceBase ovmResource = new Ovm3ResourceBase(); + 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); + } + s_logger.warn("network devices: " + _guestNetworkDevice + " " + + _privateNetworkDevice + " " + _publicNetworkDevice + " " + + _storageNetworkDevice); + + Map<String, Object> params = new HashMap<String, Object>(); + params.putAll(details); + + ovmResource.configure(hostname, params); + ovmResource.start(); + + try { + c = new Connection(hostIp, Integer.parseInt(agentPort), agentUsername, agentPassword); + } catch (Exception e) { + String msg = String.format("Cannot connect to Ovm3 agent(IP=%1$s, Port=%1$, username=%3$s, password=*******), discovery failed", + hostIp, agentPort, agentUsername); + s_logger.warn(msg); + throw new CloudRuntimeException(msg); + } + /* 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<Ovm3ResourceBase, Map<String, String>> resources = new HashMap<Ovm3ResourceBase, Map<String, String>>(); + resources.put(ovmResource, details); + return resources; + } catch (XmlRpcException e) { + s_logger.debug("XmlRpc exception, Unable to discover Ovm3 host: " + url.getHost(), + e); + return null; + } catch (UnknownHostException e) { + s_logger.debug( + "Host name resolve failed exception, Unable to discover Ovm3 host: " + + url.getHost(), e); + return null; + } catch (ConfigurationException e) { + s_logger.debug( + "Configure resource failed, Unable to discover Ovm3 host: " + url.getHost(), + e); + return null; + } catch (Exception e) { + s_logger.debug("Unable to discover Ovm3 host: " + url.getHost(), e); + return null; + } + } + + @Override + public void postDiscovery(List<HostVO> hosts, long msId) + throws CloudRuntimeException { + // TODO Auto-generated method stub + s_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) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + // TODO Auto-generated method stub + return false; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, + AgentControlCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + /* for reconnecting */ + @Override + public void processConnect(Host host, StartupCommand cmd, + boolean forRebalance) { + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRecurring() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int getTimeout() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + // TODO Auto-generated method stub + return false; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, + StartupCommand[] startup, ServerResource resource, + Map<String, String> details, List<String> hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.Ovm3) { + return null; + } + + // TODO: Double check this + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.Ovm3, + details, hostTags); + } + + // TODO: Make sure that we cleanup when the host is removed + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, + boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() != com.cloud.host.Host.Type.Routing + || host.getHypervisorType() != HypervisorType.Ovm3) { + return null; + } + + _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); + return new DeleteHostAnswer(true); + } + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Fencer.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Fencer.java new file mode 100755 index 0000000..30db663 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Fencer.java
@@ -0,0 +1,133 @@ +// 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.hypervisor; + +import java.util.List; +import java.util.Map; + +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.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.ha.FenceBuilder; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; + +@Local(value = FenceBuilder.class) +public class Ovm3Fencer extends AdapterBase implements FenceBuilder { + Map<String, Object> _params; + private static final Logger s_logger = Logger.getLogger(Ovm3Fencer.class); + @Inject + AgentManager _agentMgr; + @Inject + ResourceManager _resourceMgr; + + + @Override + public boolean configure(String name, Map<String, Object> params) + throws ConfigurationException { + _params = params; + return true; + } + + @Override + public boolean start() { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean stop() { + // TODO Auto-generated method stub + return true; + } + + public Ovm3Fencer() { + super(); + } + + @Override + public Boolean fenceOff(VirtualMachine vm, Host host) { + if (host.getHypervisorType() != HypervisorType.Ovm3) { + s_logger.debug("Don't know how to fence non Ovm3 hosts " + + host.getHypervisorType()); + return null; + } else { + s_logger.debug("Fencing " + vm + " on host " + host + + " with params: "+ _params ); + } + + List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(host + .getClusterId()); + FenceCommand fence = new FenceCommand(vm, host); + + for (HostVO h : hosts) { + if (h.getHypervisorType() != HypervisorType.Ovm3) { + continue; + } + + if (h.getStatus() != Status.Up) { + continue; + } + + if (h.getId() == host.getId()) { + continue; + } + + FenceAnswer answer; + try { + answer = (FenceAnswer) _agentMgr.send(h.getId(), fence); + } catch (AgentUnavailableException e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Moving on to the next host because " + + h.toString() + " is unavailable"); + } + continue; + } catch (OperationTimedoutException e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Moving on to the next host because " + + h.toString() + " is unavailable"); + } + continue; + } + + if (answer != null && answer.getResult()) { + return true; + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to fence off " + vm.toString() + " on " + + host.toString()); + } + + return false; + } + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Guru.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Guru.java new file mode 100755 index 0000000..08aac30 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Guru.java
@@ -0,0 +1,65 @@ +// 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. + +/* shameless rip from original ovm guru */ +package com.cloud.hypervisor.ovm3.hypervisor; + +import javax.ejb.Local; +import javax.inject.Inject; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruBase; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value = HypervisorGuru.class) +public class Ovm3Guru extends HypervisorGuruBase implements HypervisorGuru { + // private static final Logger s_logger = Logger.getLogger(VMwareGuru.class); + + @Inject + GuestOSDao _guestOsDao; + + protected Ovm3Guru() { + super(); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.Ovm3; + } + + @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { + VirtualMachineTO to = toVirtualMachineTO(vm); + to.setBootloader(vm.getBootLoaderType()); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine() + .getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + + return to; + } + + @Override + public boolean trackVmHostChange() { + return true; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Helper.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Helper.java new file mode 100755 index 0000000..8b0b1b5 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3Helper.java
@@ -0,0 +1,82 @@ +// 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.hypervisor; + +import java.util.HashMap; + +public class Ovm3Helper { + /* /usr/lib64/python2.4/site-packages/agent/lib/assembly */ + private static final HashMap<String, String> s_ovmMap = new HashMap<String, String>(); + + public static final String HVM = "hvm"; + public static final String PV = "xen_pvm"; + public static final String DOMSOL = "ldoms_pvm"; + public static final String DEFAULT = "default"; + + static { + s_ovmMap.put("Oracle Enterprise Linux 6.0 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 6.0 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.0 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.0 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.1 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.1 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.2 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.2 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.3 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.3 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.4 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.4 (64-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.5 (32-bit)", PV); + s_ovmMap.put("Oracle Enterprise Linux 5.5 (64-bit)", PV); + s_ovmMap.put("Other Linux (32-bit)", PV); + s_ovmMap.put("Other Linux (64-bit)", PV); + s_ovmMap.put("Other PV (32-bit)", PV); + s_ovmMap.put("Other PV (64-bit)", PV); + s_ovmMap.put("Debian GNU/Linux 7(32-bit)", PV); + s_ovmMap.put("Debian GNU/Linux 7(64-bit)", PV); + s_ovmMap.put("Linux HVM (32-bit)", HVM); + s_ovmMap.put("Linux HVM (64-bit)", HVM); + s_ovmMap.put("Dos", HVM); + s_ovmMap.put("Windows 7 (32-bit)", HVM); + s_ovmMap.put("Windows 7 (64-bit)", HVM); + s_ovmMap.put("Windows 8 (64-bit)", HVM); + s_ovmMap.put("Windows Server 2003 (32-bit)", HVM); + s_ovmMap.put("Windows Server 2003 (64-bit)", HVM); + s_ovmMap.put("Windows Server 2008 (32-bit)", HVM); + s_ovmMap.put("Windows Server 2008 (64-bit)", HVM); + s_ovmMap.put("Windows Server 2008 R2 (64-bit)", HVM); + s_ovmMap.put("Windows Server 2012 (64-bit)", HVM); + s_ovmMap.put("Windows 2000 SP4 (32-bit)", HVM); + s_ovmMap.put("Windows Vista (32-bit)", HVM); + s_ovmMap.put("Windows XP SP2 (32-bit)", HVM); + s_ovmMap.put("Windows XP SP3 (32-bit)", HVM); + s_ovmMap.put("Sun Solaris 10(32-bit)", HVM); + s_ovmMap.put("Sun Solaris 10(64-bit)", HVM); + s_ovmMap.put("Sun Solaris 9(Experimental)", HVM); + s_ovmMap.put("Sun Solaris 8(Experimental)", HVM); + s_ovmMap.put("Sun Solaris 11 (32-bit)", HVM); + s_ovmMap.put("Sun Solaris 11 (64-bit)", HVM); + s_ovmMap.put("Sun Solaris PV (32-bit)", PV); + s_ovmMap.put("Sun Solaris PV (64-bit)", PV); + s_ovmMap.put("Sun Solaris Sparc (32-bit)", DOMSOL); + s_ovmMap.put("Sun Solaris Sparc (64-bit)", DOMSOL); + } + + public static String getOvm3GuestType(String stdType) { + return s_ovmMap.get(stdType); + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3ResourceBase.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3ResourceBase.java new file mode 100755 index 0000000..6b563d5 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/hypervisor/Ovm3ResourceBase.java
@@ -0,0 +1,3211 @@ +// 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.hypervisor; + +import java.io.File; +import java.io.IOException; +import java.math.BigInteger; +import java.net.URI; +import java.util.ArrayList; +// import java.net.URISyntaxException; +/* + * import java.util.ArrayList; + */ +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.net.URL; + +import org.apache.commons.lang.BooleanUtils; + +import com.google.gson.Gson; + +import org.apache.commons.codec.binary.Base64; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; + + + + +// import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +// import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import com.cloud.agent.IAgentControl; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachIsoCommand; +import com.cloud.agent.api.AttachVolumeAnswer; +import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.CheckNetworkAnswer; +import com.cloud.agent.api.CheckNetworkCommand; +import com.cloud.agent.api.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +// import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.FenceAnswer; +import com.cloud.agent.api.FenceCommand; +import com.cloud.agent.api.GetHostStatsAnswer; +import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetStorageStatsAnswer; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.GetDomRVersionAnswer; +import com.cloud.agent.api.GetDomRVersionCmd; +import com.cloud.agent.api.NetworkRulesSystemVmCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.VmDataCommand; +// import com.cloud.agent.api.routing.DhcpEntryAnswer; +import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.HostVmStateReportEntry; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.PingRoutingCommand; +import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +// import com.cloud.agent.api.PrepareOCFS2NodesCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.RebootAnswer; +import com.cloud.agent.api.RebootCommand; +/* + * import com.cloud.agent.api.SecurityGroupRuleAnswer; + * import com.cloud.agent.api.SecurityGroupRulesCmd; + */ +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.StartupStorageCommand; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.storage.CopyVolumeAnswer; +import com.cloud.agent.api.storage.CopyVolumeCommand; +import com.cloud.agent.api.storage.CreateAnswer; +import com.cloud.agent.api.storage.CreateCommand; +import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; +import com.cloud.agent.api.storage.DestroyCommand; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.DataObjectType; +import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.PhysicalNetworkSetupInfo; +// import com.cloud.network.NetworkModel; +import com.cloud.resource.ServerResource; +import com.cloud.resource.hypervisor.HypervisorResource; +// import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.Volume; +import com.cloud.storage.template.TemplateProp; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +// import com.cloud.utils.Pair; +// import com.cloud.utils.Ternary; +import com.cloud.utils.exception.CloudRuntimeException; +// import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SshHelper; +import com.trilead.ssh2.SCPClient; +import com.cloud.utils.ssh.SSHCmdHelper; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineName; +import com.cloud.vm.VirtualMachine.PowerState; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.hypervisor.ovm3.object.Common; +import com.cloud.hypervisor.ovm3.object.Connection; +import com.cloud.hypervisor.ovm3.object.Linux; +import com.cloud.hypervisor.ovm3.object.Network; +import com.cloud.hypervisor.ovm3.object.OvmObject; +import com.cloud.hypervisor.ovm3.object.Pool; +import com.cloud.hypervisor.ovm3.object.PoolOCFS2; +import com.cloud.hypervisor.ovm3.object.Repository; +import com.cloud.hypervisor.ovm3.object.StoragePlugin; +import com.cloud.hypervisor.ovm3.object.Xen; +import com.cloud.hypervisor.ovm3.object.CloudStackPlugin; + +import org.apache.cloudstack.storage.command.CopyCommand; +import org.apache.cloudstack.storage.command.DeleteCommand; +import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; +import org.apache.cloudstack.storage.command.CreateObjectCommand; + +import com.cloud.storage.resource.StorageProcessor; + +import org.apache.cloudstack.storage.command.ForgetObjectCmd; +import org.apache.cloudstack.storage.command.IntroduceObjectCmd; +import org.apache.cloudstack.storage.command.DettachCommand; +// import org.apache.cloudstack.storage.command.DettachAnswer; +import org.apache.cloudstack.storage.command.AttachCommand; + + + +// import org.apache.cloudstack.storage.command.AttachAnswer; +import com.cloud.storage.Storage.ImageFormat; +/* do we need this ? */ +import com.cloud.utils.db.GlobalLock; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.script.Script; + +import org.apache.commons.io.FileUtils; + +import javax.inject.Inject; + +/* TODO: Seperate these out */ +public class Ovm3ResourceBase implements ServerResource, HypervisorResource, + StorageProcessor { + private static final Logger s_logger = Logger + .getLogger(Ovm3ResourceBase.class); + private Connection c; + private Connection m; + private String _name; + private String _ip; + Long _zoneId; + Long _podId; + Long _poolId; + Long _clusterId; + String _host; + String _guid; + String _username = "root"; + String _password; + String _agentUserName = "oracle"; + String _agentPassword; + Integer _agentPort = 8899; + Boolean _agentSsl = false; + String _ovmSshKey = "id_rsa.cloud"; + String _masterUuid = "d1a749d4295041fb99854f52ea4dea97"; + Boolean _isMaster = false; + Boolean _hasMaster = false; + Boolean _ovm3pool = false; + Boolean _ovm3cluster = false; + String _ovm3vip = ""; + protected boolean _checkHvm = false; + /* _clusterDetailsDao.findDetail(clusterId, getVagKey(storagePoolId)); */ + String _privateNetworkName; + String _publicNetworkName; + String _guestNetworkName; + String _storageNetworkName; + String _controlNetworkName = "control0"; + String _controlNetworkIp = "169.254.0.1"; + // String _controlNetworkMask = "255.255.0.0"; + boolean _canBridgeFirewall = false; + String _ovmRepo = "/OVS/Repositories"; + String _ovmSec = "/nfsmnt"; + OvmObject _ovmObject = new OvmObject(); + static boolean s_isHeartBeat = false; + protected final int DefaultDomRSshPort = 3922; + String DefaultDomRPath = "/opt/cloud/bin/"; + private Map<String, Network.Interface> _interfaces = null; + /* switch to concurrenthasmaps all over the place ? */ + private final ConcurrentHashMap<String, + Map<String, String>> _vmStats = + new ConcurrentHashMap<String, + Map<String, String>>(); + + // TODO vmsync { + /* This is replaced by the vmList in getall VMs, and operate on that */ + // protected HashMap<String, State> _vms = new HashMap<String, State>(250); + protected Map<String, Xen.Vm> _vms = new HashMap<String, Xen.Vm>(); + protected Map<String, State> _vmstates = new HashMap<String, State>(); + + static HashMap<String, State> s_stateMaps; + static { + s_stateMaps = new HashMap<String, State>(); + s_stateMaps.put("Stopping", State.Stopping); + s_stateMaps.put("Running", State.Running); + s_stateMaps.put("Stopped", State.Stopped); + s_stateMaps.put("Error", State.Error); + s_stateMaps.put("Suspended", State.Running); + s_stateMaps.put("Paused", State.Running); + s_stateMaps.put("Migrating", State.Migrating); + } + + static HashMap<String, PowerState> s_powerStateMaps; + static { + s_powerStateMaps = new HashMap<String, PowerState>(); + s_powerStateMaps.put("Stopping", PowerState.PowerOn); + s_powerStateMaps.put("Running", PowerState.PowerOn); + s_powerStateMaps.put("Stopped", PowerState.PowerOff); + s_powerStateMaps.put("Error", PowerState.PowerUnknown); + s_powerStateMaps.put("Suspended", PowerState.PowerOn); + s_powerStateMaps.put("Paused", PowerState.PowerOn); + /* unknown ? */ + s_powerStateMaps.put("Migrating", PowerState.PowerOn); + } + + @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + HostDao _hostDao; + @Inject + ResourceManager _resourceMgr; + + GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("ovm3.exclusive.op"); + + /* return params we want to add, damnit */ + @Override + public boolean configure(String name, Map<String, Object> params) + throws ConfigurationException { + _name = name; + s_logger.debug("configure " + name + " with params: " + params); + /* do we have enough ? */ + try { + _zoneId = Long.parseLong((String) params.get("zone")); + _podId = Long.parseLong((String) params.get("pod")); + _clusterId = Long.parseLong((String) params.get("cluster")); + _ovm3vip = String.valueOf(params.get("ovm3vip")); + _ovm3pool = BooleanUtils.toBoolean((String) params.get("ovm3pool")); + _ovm3cluster = BooleanUtils.toBoolean((String) params + .get("ovm3cluster")); + _host = (String) params.get("host"); + _ip = (String) params.get("ip"); + _username = (String) params.get("username"); + _password = (String) params.get("password"); + _guid = (String) params.get("guid"); + _agentUserName = (String) params.get("agentusername"); + _agentPassword = (String) params.get("agentpassword"); + _privateNetworkName = (String) params.get("private.network.device"); + _publicNetworkName = (String) params.get("public.network.device"); + _guestNetworkName = (String) params.get("guest.network.device"); + _storageNetworkName = (String) params.get("storage.network.device"); + + if (params.get("agentport") != null) + _agentPort = Integer.parseInt((String) params.get("agentport")); + + // Add later + // _agentSsl = (Boolean)params.get("agentssl"); + } catch (Exception e) { + s_logger.debug("Configure " + _host + " failed", e); + throw new ConfigurationException("Configure " + _host + " failed, " + + e.toString()); + } + + if (_podId == null) { + String msg = "Unable to get the pod"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_host == null) { + String msg = "Unable to get the host"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_username == null) { + String msg = "Unable to get the username"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_password == null) { + String msg = "Unable to get the password"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_guid == null) { + String msg = "Unable to get the guid"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_agentUserName == null) { + String msg = "Unable to get the agent username"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_agentPassword == null) { + String msg = "Unable to get the agent password"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + if (_agentPort == null) { + String msg = "Unable to get the agent port"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + + /* TODO: Needs to be relocated */ + if (_ovm3vip.equals("")) { + s_logger.debug("No VIP, Setting ovm3pool and ovm3cluster to false"); + this._ovm3pool = false; + this._ovm3cluster = false; + this._ovm3vip = ""; + } + /* if we're a cluster we have to be a pool ? */ + if (_ovm3cluster) { + this._ovm3pool = true; + } + + /* check if we're master or not and if we can connect */ + try { + try { + c = new Connection(_host, _agentPort, _agentUserName, + _agentPassword); + } catch (XmlRpcException ex) { + String msg = "Unable to connect to " + _host; + s_logger.warn(msg + ": " + ex.getMessage()); + throw new Exception(msg, ex); + } + this._isMaster = masterCheck(); + } catch (Exception e) { + String msg = "Base checks failed for " + _host; + s_logger.debug(msg, e); + throw new ConfigurationException(msg); + } + /* setup ovm3 plugin */ + try { + installOvsPlugin(); + CloudStackPlugin cSp = new CloudStackPlugin(c); + cSp.ovsUploadSshKey(this._ovmSshKey, + FileUtils.readFileToString(getSystemVMKeyFile())); + } catch (Exception e) { + String msg = "Failed to setup server: " + _host; + s_logger.error(msg + ": " + e.getMessage()); + throw new ConfigurationException(msg + ", " + e); + } + + try { + try { + /* + * TODO: setup meta tags for the management interface (probably + * required with multiple interfaces)? + */ + Network net = new Network(c); + _interfaces = net.getInterfaceList(); + s_logger.debug("all interfaces: " + _interfaces); + if (_controlNetworkName != null + && !_interfaces.containsKey(_controlNetworkName)) { + /* + * TODO: find a more elegant way to do this + * for now we need the route del and ifconfig + * as loopback bridges have arp disabled by default, + * and zeroconf configures a route on the main bridge... + */ + try { + net.startOvsLocalConfig(_controlNetworkName); + } catch (Exception e) { + s_logger.debug("Unable to configure" + + _controlNetworkName + ":" + e.getMessage()); + } + /* ovs replies too "fast" so the bridge can be "busy" */ + while (!_interfaces.containsKey(_controlNetworkName)) { + s_logger.debug("waiting for " + _controlNetworkName); + _interfaces = net.getInterfaceList(); + Thread.sleep(1 * 1000); + } + } + /* The bridge is remembered upon reboot, but not the IP */ + net.ovsIpConfig(_controlNetworkName, + "static", + _controlNetworkIp, + "255.255.0.0"); + CloudStackPlugin cSp = new CloudStackPlugin(c); + cSp.ovsControlInterface(_controlNetworkName, + _controlNetworkIp + "/16"); + + // Missing netM = new Missing(c); + /* build ovs_if_meta in Net based on the following */ + if (_privateNetworkName != null + && net.getBridgeByName(_privateNetworkName).getName() == null) { + throw new ConfigurationException( + "Cannot find private bridge " + + _privateNetworkName + + " on host " + + _host + + " - " + + net.getBridgeByName(_privateNetworkName) + .getName()); + } + if (_publicNetworkName != null + && net.getBridgeByName(_publicNetworkName).getName() == null) { + throw new ConfigurationException( + "Cannot find private bridge " + + _publicNetworkName + + " on host " + + _host + + " - " + + net.getBridgeByName(_publicNetworkName) + .getName()); + } + if (_guestNetworkName != null + && net.getBridgeByName(_guestNetworkName).getName() == null) { + throw new ConfigurationException( + "Cannot find private bridge " + + _guestNetworkName + + " on host " + + _host + + " - " + + net.getBridgeByName(_guestNetworkName) + .getName()); + } + if (_storageNetworkName != null + && net.getBridgeByName(_storageNetworkName).getName() == null) { + throw new ConfigurationException( + "Cannot find private bridge " + + _storageNetworkName + + " on host " + + _host + + " - " + + net.getBridgeByName(_storageNetworkName) + .getName()); + } + } catch (Exception e) { + s_logger.debug("Get bridges failed on host " + _host + ", ", e); + throw new ConfigurationException("Cannot get bridges on host " + + _host + ", " + e); + } + try { + prepareForPool(); + } catch (Exception e) { + throw new ConfigurationException("Failed to prepare for pool " + + _host + ", " + e); + } + + /* + * set to false so each time ModifyStoragePoolCommand will re-setup + * heartbeat + */ + /* + * only required if we do cluster and then o2cb will take care of it + * s_isHeartBeat = false; + */ + + /* + * - uses iptables in XenServer, but not agent accessible for agent + * *should make module* + */ + try { + _canBridgeFirewall = canBridgeFirewall(); + } catch (XmlRpcException e) { + s_logger.error("Failed to detect whether the host supports security groups.", + e); + _canBridgeFirewall = false; + } + + s_logger.debug(_canBridgeFirewall ? "OVM3 host supports security groups." + : "OVM3 host doesn't support security groups."); + /* + * } catch (XmlRpcException e) { + * String msg = "XML RPC Exception, unable to setup host: " + _host + * + " " + e; + * s_logger.debug(msg); + * throw new ConfigurationException(msg); + */ + } catch (Exception e) { + String msg = "Generic Exception, failed to setup host: " + _host; + s_logger.debug(msg + ": " + e.getMessage()); + throw new ConfigurationException(msg + ":" + e.getMessage()); + } /* + * catch (IOException e) { s_logger.debug("Failed to setup host " + + * _host, e); throw new + * ConfigurationException("Unable to setup host"); } + */ + return true; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public Type getType() { + return Type.Routing; + } + + protected void fillHostInfo(StartupRoutingCommand cmd) { + try { + /* get data we need from parts */ + Linux host = new Linux(c); + if (!host.getOvmVersion().startsWith("3.2.")) { + throw new CloudRuntimeException( + "OVM 3.2.X is only supported, not " + + host.getOvmVersion()); + } + Xen vms = new Xen(c); + vms.listVms(); + Xen.Vm dom0 = vms.getRunningVmConfig("Domain-0"); + + cmd.setName(host.getHostName()); + cmd.setSpeed(host.getCpuKhz()); + cmd.setCpus(host.getTotalThreads()); + cmd.setCpuSockets(host.getCpuSockets()); + cmd.setMemory(host.getMemory().longValue()); + /* + * TODO: Convert Bigint to long in Linux + */ + BigInteger totalmem = BigInteger.valueOf(host.getMemory() + .longValue()); + BigInteger freemem = BigInteger.valueOf(host.getFreeMemory() + .longValue()); + cmd.setDom0MinMemory(totalmem.subtract(freemem).longValue()); + // setPoolSync and setCaps. + cmd.setGuid(_guid); + cmd.setDataCenter(_zoneId.toString()); + cmd.setPod(_podId.toString()); + // also set uuid for ownership, or else pooling/clustering will not + // work + // cmd.setOwner(host.getManagerUuid()); + cmd.setCluster(_clusterId.toString()); + cmd.setHypervisorVersion(host.getOvmVersion()); + cmd.setVersion(host.getAgentVersion()); + cmd.setHypervisorType(HypervisorType.Ovm3); + /* is this true ? */ + cmd.setCaps(host.getCapabilities()); + // TODO: Control ip, for now cheat ? + cmd.setPrivateIpAddress(_ip); + cmd.setStorageIpAddress(_ip); + cmd.setHostVmStateReport(HostVmStateReport()); + + Network net = new Network(c); + /* more detail -- fix -- and shouldn't matter */ + /* should this be the bond before the bridge ?*/ + String defaultBridge = net.getBridgeByIp(_ip).getName(); + if (defaultBridge == null) { + throw new CloudRuntimeException( + "Unable to obtain valid bridge with " + _ip); + } + + /* TODO: cleanup network section, this is not right */ + if (_publicNetworkName == null) { + _publicNetworkName = defaultBridge; + } + if (_privateNetworkName == null) { + _privateNetworkName = _publicNetworkName; + } + if (_guestNetworkName == null) { + _guestNetworkName = _publicNetworkName; + } + /* + * if (_storageNetworkName == null) { + * _storageNetworkName = _privateNetworkName; + * } + */ + Map<String, String> d = cmd.getHostDetails(); + d.put("public.network.device", _publicNetworkName); + if (_privateNetworkName != null) + d.put("private.network.device", _privateNetworkName); + if (_guestNetworkName != null) + d.put("guest.network.device", _guestNetworkName); + if (_storageNetworkName != null) + d.put("storage.network.device", _storageNetworkName); + d.put("ismaster", this._isMaster.toString()); + cmd.setHostDetails(d); + s_logger.debug("Add an Ovm3 host " + _name + ":" + + cmd.getHostDetails()); + } catch (XmlRpcException e) { + s_logger.debug("XML RPC Exception" + e.getMessage(), e); + throw new CloudRuntimeException("XML RPC Exception" + + e.getMessage(), e); + } catch (Exception e) { + s_logger.debug("Exception " + e.getMessage(), e); + throw new CloudRuntimeException("Exception" + e.getMessage(), e); + } + } + + /* + * plugs the ovm module into the ovs-agent + */ + protected void installOvsPlugin() throws IOException { + /* ssh-copy-id anyone ? */ + try { + com.trilead.ssh2.Connection sshConnection = + SSHCmdHelper.acquireAuthorizedConnection(_ip, + _username, + _password); + if (sshConnection == null) { + throw new ConfigurationException(String.format("Unable to " + + "connect to server(IP=%1$s, username=%2$s, " + + "password=%3$s", _ip, _username, _password)); + } + SCPClient scp = new SCPClient(sshConnection); + String userDataScript = "scripts/vm/hypervisor/ovm3/cloudstack.py"; + String userDataScriptPath = Script.findScript("", userDataScript); + if (userDataScriptPath == null) { + throw new ConfigurationException("Can not find " + + userDataScript); + } + scp.put(userDataScriptPath, "", "0755"); + String prepareCmd = String.format("./cloudstack.py " + + "--ssl=" + this._agentSsl + " " + + "--port=" + this._agentPort); + if (!SSHCmdHelper.sshExecuteCmd(sshConnection, prepareCmd)) { + throw new ConfigurationException("Module insertion at " + + _host + " failed"); + } + } catch (Exception es) { + s_logger.error("Unexpected exception ", es); + String msg = "Unable to install module in agent"; + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + /* startup */ + @Override + public StartupCommand[] initialize() { + s_logger.debug("Ovm3 resource intializing"); + try { + StartupRoutingCommand srCmd = new StartupRoutingCommand(); + + StartupStorageCommand ssCmd = new StartupStorageCommand(); + fillHostInfo(srCmd); + String pool = srCmd.getPool(); + s_logger.debug("Ovm3 pool " + ssCmd + " " + srCmd); + + Map<String, State> changes = null; + synchronized (_vmstates) { + _vmstates.clear(); + changes = sync(); + } + srCmd.setStateChanges(changes); + /* should not force HVM */ + // cmd.setCaps("hvm"); + return new StartupCommand[] { srCmd, ssCmd }; + } catch (Exception e) { + s_logger.debug("Ovm3 resource initializes failed", e); + return null; + } + } + + /* See if the agent is still up on the host */ + @Override + public PingCommand getCurrentStatus(long id) { + try { + /* feels useless somehow */ + Common test = new Common(c); + String ping = "put"; + String pong = test.echo(ping); + if (pong.contains(ping)) { + HashMap<String, State> newStates = sync(); + return new PingRoutingCommand(getType(), id, newStates, + HostVmStateReport()); + } + } catch (XmlRpcException e) { + s_logger.debug("Check agent status failed", e); + return null; + } catch (Exception e) { + s_logger.debug("Check agent status failed", e); + return null; + } + return null; + } + + /* Check if the host is in ready state for CS */ + protected ReadyAnswer execute(ReadyCommand cmd) { + try { + Linux host = new Linux(c); + Pool pool = new Pool(c); + + /* only interesting when doing cluster */ + if (!host.getIsMaster() && _ovm3cluster) { + if (pool.getPoolMasterVip().equalsIgnoreCase(_ip)) { + /* check pool state here */ + return new ReadyAnswer(cmd); + } else { + s_logger.debug("Master IP changes to " + + pool.getPoolMasterVip() + ", it should be " + _ip); + return new ReadyAnswer(cmd, "I am not the master server"); + } + } else if (host.getIsMaster()) { + s_logger.debug("Master, not clustered " + _host); + return new ReadyAnswer(cmd); + } else { + s_logger.debug("No master, not clustered " + _host); + return new ReadyAnswer(cmd); + } + } catch (XmlRpcException e) { + s_logger.debug("XML RPC Exception" + e.getMessage(), e); + throw new CloudRuntimeException("XML RPC Exception" + + e.getMessage(), e); + } catch (Exception e) { + s_logger.debug("Exception" + e.getMessage(), e); + throw new CloudRuntimeException("Exception" + e.getMessage(), e); + } + + } + + /* + * Primary storage, will throw an error if ownership does not match! + * Pooling is a part of this, for now + */ + protected boolean createRepo(StorageFilerTO cmd) throws XmlRpcException { + String basePath = this._ovmRepo; + Repository repo = new Repository(c); + String primUuid = repo.deDash(cmd.getUuid()); + String ovsRepo = basePath + "/" + primUuid; + /* should add port ? */ + String mountPoint = String.format("%1$s:%2$s", + cmd.getHost(), + cmd.getPath()); + + String msg; + if (cmd.getType() == StoragePoolType.NetworkFilesystem) { + /* base repo first */ + + repo.mountRepoFs(mountPoint, ovsRepo); + s_logger.debug("NFS repository " + mountPoint + " on " + ovsRepo + + " requested for " + _host); + try { + repo.addRepo(mountPoint, ovsRepo); + } catch (Exception e) { + s_logger.debug("NFS repository " + mountPoint + " on " + + ovsRepo + " not found creating!"); + try { + repo.createRepo(mountPoint, + ovsRepo, + primUuid, + "OVS Reposutory"); + } catch (Exception es) { + msg = "NFS repository " + mountPoint + " on " + + ovsRepo + " create failed!"; + s_logger.debug(msg); + throw new CloudRuntimeException( + msg + " " + es.getMessage(), es); + } + } + /* add base pooling first */ + if (this._ovm3pool) { + try { + msg = "Configuring host for pool"; + s_logger.debug(msg); + setupPool(cmd); + msg = "Configured host for pool"; + /* add clustering after pooling */ + if (this._ovm3cluster) { + msg = "Configuring host for cluster"; + s_logger.debug(msg); + /* setup cluster */ + /* + * From cluster.java + * configure_server_for_cluster(cluster conf, fs, mount, + * fsuuid, poolfsbaseuuid) + */ + /* create_cluster(poolfsuuid,) */ + msg = "Configuring host for cluster"; + } + } catch (Exception e) { + msg = "Unable to setup pool on " + ovsRepo; + s_logger.debug(msg); + throw new CloudRuntimeException(msg + " " + e.getMessage(), e); + } + } else { + msg = "no way dude I can't stand for this"; + s_logger.debug(msg); + } + /* + * this is to create the .generic_fs_stamp else we're not allowed + * to create any data\disks on this thing + */ + try { + URI uri = new URI(cmd.getType() + "://" + cmd.getHost() + ":" + + +cmd.getPort() + cmd.getPath() + "/VirtualMachines"); + this.setupNfsStorage(uri, cmd.getUuid()); + } catch (Exception e) { + msg = "NFS mount " + mountPoint + " on " + _ovmSec + "/" + + cmd.getUuid() + " create failed!"; + s_logger.debug(msg); + throw new CloudRuntimeException(msg + " " + e.getMessage(), e); + } + } else { + msg = "NFS repository " + mountPoint + " on " + ovsRepo + + " create failed, was type " + cmd.getType(); + s_logger.debug(msg); + return false; + } + + try { + /* systemvm iso is imported here */ + prepareSecondaryStorageStore(ovsRepo); + } catch (Exception e) { + msg = "systemvm.iso copy failed to " + ovsRepo; + s_logger.debug(msg); + return false; + } + return true; + } + + /* */ + public void prepareSecondaryStorageStore(String storageUrl) { + String mountPoint = storageUrl; + + GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm"); + try { + /* double check */ + if (this._hasMaster && this._ovm3pool) { + s_logger.debug("Skip systemvm iso copy, leave it to the master"); + return; + } + if (lock.lock(3600)) { + try { + File srcIso = getSystemVMPatchIsoFile(); + String destPath = mountPoint + "/ISOs/"; + String repoPath[] = mountPoint.split(File.separator); + String destIso = destPath + "/" + + getSystemVMIsoFileNameOnDatastore(); + String result = ""; + try { + StoragePlugin sp = new StoragePlugin(c); + // sp.storagePluginGetFileInfo(repoPath[repoPath.length], + // destIso); + if (sp.getFileSize() > 0) { + s_logger.info(" System VM patch ISO file already exists: " + + srcIso.getAbsolutePath().toString() + + ", destination: " + destIso); + } + } catch (Exception e) { + /* + * Cloudstack already does this at boot time: + * s_logger.info( + * "Inject SSH key pairs before copying systemvm.iso into secondary storage" + * ); + */ + s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " + + srcIso.getAbsolutePath() + + ", destination: " + + destIso); + try { + /* + * should actualy come from importIso in + * Storageplugin, so craft a url that can be used + * for that. + */ + SshHelper.scpTo(this._host, + 22, + this._username, + null, + this._password, + destPath, + srcIso.getAbsolutePath().toString(), + "0644"); + } catch (Exception es) { + s_logger.error("Unexpected exception ", es); + String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + + srcIso.toString() + + ", dest location: " + + destIso; + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + } finally { + lock.unlock(); + } + } + } finally { + lock.releaseRef(); + } + } + + /* stolen from vmware impl */ + public String getSystemVMIsoFileNameOnDatastore() { + String version = this.getClass().getPackage() + .getImplementationVersion(); + String fileName = "systemvm-" + version + ".iso"; + return fileName.replace(':', '-'); + } + + /* stolen from vmware impl */ + private File getSystemVMPatchIsoFile() { + // locate systemvm.iso + String svmName = getSystemVMIsoFileNameOnDatastore(); + URL url = this.getClass().getClassLoader() + .getResource("vms/" + svmName); + s_logger.debug(url); + File isoFile = null; + if (url != null) { + isoFile = new File(url.getPath()); + } + if (isoFile == null || !isoFile.exists()) { + isoFile = new File("/usr/share/cloudstack-common/vms/" + svmName); + } + + assert (isoFile != null); + if (!isoFile.exists()) { + s_logger.error("Unable to locate " + svmName + " in your setup at " + + isoFile.toString()); + } + return isoFile; + } + + /* get the key */ + public File getSystemVMKeyFile() { + URL url = this.getClass().getClassLoader() + .getResource("scripts/vm/systemvm/" + this._ovmSshKey); + File keyFile = null; + if (url != null) { + keyFile = new File(url.getPath()); + } + if (keyFile == null || !keyFile.exists()) { + keyFile = new File( + "/usr/share/cloudstack-common/scripts/vm/systemvm/" + + _ovmSshKey); + } + assert (keyFile != null); + if (!keyFile.exists()) { + s_logger.error("Unable to locate " + _ovmSshKey + + " in your setup at " + keyFile.toString()); + } + return keyFile; + } + + /* + * TODO: local OCFS2? or iSCSI OCFS2 + */ + protected Boolean createOCFS2Sr(StorageFilerTO pool) throws XmlRpcException { + /* + * Ovm3StoragePool.Details d = new Ovm3StoragePool.Details(); d.path = + * pool.getPath(); d.type = Ovm3StoragePool.OCFS2; d.uuid = + * pool.getUuid(); Ovm3StoragePool.create(_conn, d); + * s_logger.debug(String.format("Created SR (mount point:%1$s)", + * d.path)); + */ + s_logger.debug("OCFS2 Not implemented yet"); + return false; + } + + /* TODO: heartbeats are done by the oracle cluster when clustering */ + private void setupHeartBeat(String poolUuid) { + try { + if (!s_isHeartBeat) { + // Ovm3Host.setupHeartBeat(_conn, poolUuid, _ip); + s_isHeartBeat = true; + } + } catch (Exception e) { + s_logger.debug("setup heart beat for " + _host + " failed", e); + s_isHeartBeat = false; + } + } + + /* Setup a storage pool and also get the size */ + protected Answer execute(ModifyStoragePoolCommand cmd) { + StorageFilerTO pool = cmd.getPool(); + s_logger.debug("modifying pool " + pool); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + /* this should actually not be here */ + createRepo(pool); + } else if (pool.getType() == StoragePoolType.OCFS2) { + createOCFS2Sr(pool); + } else { + return new Answer(cmd, false, "The pool type: " + + pool.getType().name() + " is not supported."); + } + + if (this._ovm3cluster) { + // setupHeartBeat(pool.getUuid()); + } + /* TODO: needs to be in network fs above */ + StoragePlugin store = new StoragePlugin(c); + String propUuid = store.deDash(pool.getUuid()); + String mntUuid = pool.getUuid(); + String nfsHost = pool.getHost(); + String nfsPath = pool.getPath(); + store.setUuid(propUuid); + store.setSsUuid(propUuid); + store.setMntUuid(mntUuid); + store.setFsHost(nfsHost); + store.setFsSourcePath(nfsHost + ":" + nfsPath); + store.storagePluginGetFileSystemInfo(); + + Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>(); + ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, + Long.parseLong(store.getTotalSize()), Long.parseLong(store + .getFreeSize()), tInfo); + return answer; + } catch (Exception e) { + s_logger.debug("ModifyStoragePoolCommand failed", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + /* TODO: add iSCSI */ + protected Answer execute(CreateStoragePoolCommand cmd) { + StorageFilerTO pool = cmd.getPool(); + s_logger.debug("creating pool " + pool); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + createRepo(pool); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + return new Answer(cmd, false, + "iSCSI is unsupported at the moment"); + // getIscsiSR(conn, pool.getUuid(), pool.getHost(), + // pool.getPath(), null, null, false); + } else if (pool.getType() == StoragePoolType.OCFS2) { + return new Answer(cmd, false, + "OCFS2 is unsupported at the moment"); + } else if (pool.getType() == StoragePoolType.PreSetup) { + s_logger.warn("pre setup for pool " + pool); + } else { + return new Answer(cmd, false, "The pool type: " + + pool.getType().name() + " is not supported."); + } + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + + ", create StoragePool failed due to " + e.toString() + + " on host:" + _host + " pool: " + pool.getHost() + + pool.getPath(); + s_logger.warn(msg, e); + return new Answer(cmd, false, msg); + } + return new Answer(cmd, true, "success"); + } + + /* + * Download some primary storage into the repository, we need the repoid to + * do that, but also have a uuid for the disk... + * TODO: check disk + * TODO: looks like we don't need this for now! (dead code) + */ + protected PrimaryStorageDownloadAnswer execute( + final PrimaryStorageDownloadCommand cmd) { + try { + Repository repo = new Repository(c); + String tmplturl = cmd.getUrl(); + String poolName = cmd.getPoolUuid(); + String image = repo.deDash(repo.newUuid()) + ".raw"; + + /* url to download from, image name, and repo to copy it to */ + repo.importVirtualDisk(tmplturl, image, poolName); + + /* TODO: return uuid and size */ + return new PrimaryStorageDownloadAnswer(image); + } catch (Exception e) { + s_logger.debug("PrimaryStorageDownloadCommand failed", e); + return new PrimaryStorageDownloadAnswer(e.getMessage()); + } + } + + /* + * TODO: Split out in Sec to prim and prim to prim and types ? + * Storage mount also goes in here for secstorage + */ + protected final Answer execute(final CopyCommand cmd) { + DataTO srcData = cmd.getSrcTO(); + DataStoreTO srcStore = srcData.getDataStore(); + DataTO destData = cmd.getDestTO(); + DataStoreTO destStore = destData.getDataStore(); + + try { + /* target and source are NFS and TEMPLATE */ + if ((srcStore instanceof NfsTO) + && (srcData.getObjectType() == DataObjectType.TEMPLATE) + && (destData.getObjectType() == DataObjectType.TEMPLATE)) { + NfsTO srcImageStore = (NfsTO) srcStore; + TemplateObjectTO srcTemplate = (TemplateObjectTO) srcData; + String storeUrl = srcImageStore.getUrl(); + + URI uri = new URI(storeUrl); + String secPoolUuid = setupSecondaryStorage(storeUrl); + String primaryPoolUuid = destData.getDataStore().getUuid(); + String destPath = this._ovmRepo + "/" + + _ovmObject.deDash(primaryPoolUuid) + "/" + + "Templates"; + String sourcePath = this._ovmSec + "/" + secPoolUuid; + + Linux host = new Linux(c); + String destUuid = srcTemplate.getUuid(); + /* + * TODO: add dynamic formats (tolower), it also supports VHD and + * QCOW2, although Ovm3.2 does not have tapdisk2 anymore so we + * can forget about that. + */ + /* TODO: add checksumming */ + String srcFile = sourcePath + "/" + srcData.getPath(); + if (srcData.getPath().endsWith("/")) { + srcFile = sourcePath + "/" + srcData.getPath() + "/" + + destUuid + ".raw"; + } + String destFile = destPath + "/" + destUuid + ".raw"; + s_logger.debug("CopyFrom: " + srcData.getObjectType() + "," + + srcFile + " to " + destData.getObjectType() + "," + + destFile); + host.copyFile(srcFile, destFile); + + TemplateObjectTO newVol = new TemplateObjectTO(); + newVol.setUuid(destUuid); + newVol.setPath(destPath); + newVol.setFormat(ImageFormat.RAW); + return new CopyCmdAnswer(newVol); + /* we assume the cache for templates is local */ + } else if ((srcData.getObjectType() == DataObjectType.TEMPLATE) + && (destData.getObjectType() == DataObjectType.VOLUME)) { + if (srcStore.getUrl().equals(destStore.getUrl())) { + TemplateObjectTO srcTemplate = (TemplateObjectTO) srcData; + VolumeObjectTO dstVolume = (VolumeObjectTO) destData; + + String srcFile = srcTemplate.getPath() + "/" + + srcTemplate.getUuid() + ".raw"; + String vDisksPath = srcTemplate.getPath() + .replace("Templates", "VirtualDisks"); + String destFile = vDisksPath + "/" + dstVolume.getUuid() + + ".raw"; + + Linux host = new Linux(c); + s_logger.debug("CopyFrom: " + srcData.getObjectType() + "," + + srcFile + " to " + destData.getObjectType() + "," + + destFile); + host.copyFile(srcFile, destFile); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setUuid(dstVolume.getUuid()); + newVol.setPath(vDisksPath); + newVol.setFormat(ImageFormat.RAW); + return new CopyCmdAnswer(newVol); + } else { + s_logger.debug("Primary to Primary doesn't match"); + } + } else { + String msg = "Unable to do stuff for " + srcStore.getClass() + + ":" + srcData.getObjectType() + " to " + + destStore.getClass() + ":" + destData.getObjectType(); + s_logger.debug(msg); + } + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + + " for template due to " + e.toString(); + s_logger.warn(msg, e); + return new CopyCmdAnswer(msg); + } + return new CopyCmdAnswer("not implemented yet"); + } + + protected Answer execute(DeleteCommand cmd) { + DataTO data = cmd.getData(); + s_logger.debug("Deleting object: " + data.getObjectType()); + if (data.getObjectType() == DataObjectType.VOLUME) { + return deleteVolume(cmd); + } else if (data.getObjectType() == DataObjectType.SNAPSHOT) { + + } else if (data.getObjectType() == DataObjectType.TEMPLATE) { + + } else { + + } + String msg = "Delete not implemented yet for this object"; + s_logger.debug(msg); + return new Answer(cmd); + } + + /* TODO: Create a Disk from a template needs cleaning */ + protected CreateAnswer execute(CreateCommand cmd) { + StorageFilerTO primaryStorage = cmd.getPool(); + DiskProfile disk = cmd.getDiskCharacteristics(); + + /* disk should have a uuid */ + String fileName = UUID.randomUUID().toString() + ".img"; + String dst = primaryStorage.getPath() + "/" + primaryStorage.getUuid() + + "/" + fileName; + + try { + StoragePlugin store = new StoragePlugin(c); + store.setUuid(primaryStorage.getUuid()); + store.setName(primaryStorage.getUserInfo()); + store.setSsUuid(primaryStorage.getUserInfo()); + if (cmd.getTemplateUrl() != null) { + s_logger.debug("CreateCommand " + cmd.getTemplateUrl() + " " + + dst); + Linux host = new Linux(c); + host.copyFile(cmd.getTemplateUrl(), dst); + } else { + /* this is a dup with the createVolume ? */ + s_logger.debug("CreateCommand " + dst); + store.storagePluginCreate(primaryStorage.getUuid(), + primaryStorage.getHost(), + dst, + disk.getSize()); + } + + store.storagePluginGetFileInfo(dst); + VolumeTO volume = new VolumeTO(cmd.getVolumeId(), disk.getType(), + primaryStorage.getType(), primaryStorage.getUuid(), + primaryStorage.getPath(), fileName, store.getFileName(), + store.getFileSize(), null); + return new CreateAnswer(cmd, volume); + } catch (Exception e) { + s_logger.debug("CreateCommand failed", e); + return new CreateAnswer(cmd, e.getMessage()); + } + } + + /* + * Add rootdisk, datadisk and iso's + */ + protected Boolean createVbds(Xen.Vm vm, VirtualMachineTO spec) { + for (DiskTO volume : spec.getDisks()) { + try { + if (volume.getType() == Volume.Type.ROOT) { + VolumeObjectTO vol = (VolumeObjectTO) volume.getData(); + DataStoreTO ds = (DataStoreTO) vol.getDataStore(); + String dsk = vol.getPath() + "/" + vol.getUuid() + ".raw"; + vm.addRootDisk(dsk); + /* TODO: needs to be replaced by rootdiskuuid? */ + vm.setPrimaryPoolUuid(ds.getUuid()); + s_logger.debug("Adding root disk: " + dsk); + } else if (volume.getType() == Volume.Type.ISO) { + DataTO isoTO = volume.getData(); + if (isoTO.getPath() != null) { + TemplateObjectTO template = (TemplateObjectTO) isoTO; + DataStoreTO store = template.getDataStore(); + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException( + "unsupported protocol"); + } + NfsTO nfsStore = (NfsTO) store; + String secPoolUuid = setupSecondaryStorage(nfsStore + .getUrl()); + String isoPath = this._ovmSec + File.separator + + secPoolUuid + File.separator + + template.getPath(); + // + template.getUuid() + ".iso"; + vm.addIso(isoPath); + /* check if secondary storage is mounted */ + s_logger.debug("Adding ISO: " + isoPath); + } + } else if (volume.getType() == Volume.Type.DATADISK) { + vm.addDataDisk(volume.getData().getPath()); + s_logger.debug("Adding data disk: " + + volume.getData().getPath()); + } else { + throw new CloudRuntimeException("Unknown volume type: " + + volume.getType()); + } + } catch (Exception e) { + s_logger.debug("CreateVbds failed", e); + throw new CloudRuntimeException("Exception" + e.getMessage(), e); + } + } + return true; + } + + /* TODO: iptables/etables logic in the supporting libs ? */ + protected Boolean createVifs(Xen.Vm vm, VirtualMachineTO spec) { + NicTO[] nics = spec.getNics(); + for (NicTO nic : nics) { + if (nic.isSecurityGroupEnabled()) { + if (spec.getType().equals(VirtualMachine.Type.User)) { + /* + * defaultNetworkRulesForUserVm(vmName, vmSpec.getId(), + * nic); + */ + } + } + try { + if (getNetwork(nic) != null) + vm.addVif(nic.getDeviceId(), getNetwork(nic), nic.getMac()); + } catch (Exception e) { + String msg = "Unable to add vif " + nic.getType() + " for " + + spec.getName() + " " + e.getMessage(); + s_logger.debug(msg); + throw new CloudRuntimeException(msg); + } + } + vm.setupVifs(); + return true; + } + + /* + * TODO: ovs calls ? depending on the type of network + * TODO: get the bridge on a per VM base so we can throw it away? + */ + private String createVlanBridge(String networkName, Integer vlanId) + throws XmlRpcException { + if (vlanId < 2 || vlanId > 4094) { + throw new CloudRuntimeException("Vlan " + vlanId + + " needs to be between 1-4095"); + } + Network net = new Network(c); + /* figure out if our bridged vlan exists, if not then create */ + String brName = networkName + "." + vlanId.toString(); + try { + String physInterface = net.getPhysicalByBridgeName(networkName); + String physVlanInt = physInterface + "." + vlanId; + + if (net.getInterfaceByName(physVlanInt) == null) + net.startOvsVlanConfig(physInterface, vlanId); + + if (net.getInterfaceByName(brName) == null) + net.startOvsBrConfig(brName, physVlanInt); + } catch (Exception e) { + throw new CloudRuntimeException("Unable to create vlan " + + vlanId.toString() + " bridge for " + networkName + + e.getMessage()); + } + return brName; + } + + // TODO: complete all network support + protected String getNetwork(NicTO nic) throws XmlRpcException { + String vlanId = null; + String bridgeName = null; + if (nic.getBroadcastType() == BroadcastDomainType.Vlan) { + vlanId = BroadcastDomainType.getValue(nic.getBroadcastUri()); + } + + if (nic.getType() == TrafficType.Guest) { + if (nic.getBroadcastType() == BroadcastDomainType.Vlan + && !vlanId.equalsIgnoreCase("untagged")) { + bridgeName = createVlanBridge(_guestNetworkName, + Integer.valueOf(vlanId)); + } else { + bridgeName = _guestNetworkName; + } + } else if (nic.getType() == TrafficType.Control) { + bridgeName = _controlNetworkName; + } else if (nic.getType() == TrafficType.Public) { + bridgeName = _publicNetworkName; + } else if (nic.getType() == TrafficType.Management) { + bridgeName = _privateNetworkName; + } else if (nic.getType() == TrafficType.Storage) { + /* TODO: Add storage network */ + bridgeName = _storageNetworkName; + } else { + throw new CloudRuntimeException("Unknown network traffic type:" + + nic.getType()); + } + return bridgeName; + } + + /* This is not create for us, but really start */ + protected boolean startVm(String repoId, String vmId) + throws XmlRpcException { + Xen host = new Xen(c); + try { + if (host.getRunningVmConfig(vmId) == null) { + s_logger.error("Create VM " + vmId + " first on " + c.getIp()); + return false; + } else { + s_logger.info("VM " + vmId + " exists on " + c.getIp()); + } + host.startVm(repoId, vmId); + } catch (Exception e) { + s_logger.error("Failed to start VM " + vmId + " on " + c.getIp() + + " " + e.getMessage()); + return false; + } + return true; + } + + /* + * TODO: OVM already cleans stuff up, just not the extra bridges which we + * don't want right now, as we'd have to keep a state table of which vlans + * need to stay on the host!? + * A map with vlanid -> list-o-hosts + */ + private void cleanupNetwork(List<String> vifs) throws XmlRpcException { + /* peel out vif info for vlan stuff */ + /* + * for (String vif : vifs) { if (vif.bridge.startsWith("vlan")) { + * Network net = new Network(c); net.ovsVlanBridgeStop(br, net, vlan); + * // Ovm3Bridge.deleteVlanBridge(_conn, vif.bridge); } } + */ + } + + protected void cleanup(Xen.Vm vm) { + try { + cleanupNetwork(vm.getVmVifs()); + } catch (XmlRpcException e) { + s_logger.debug("Clean up network for " + vm.getVmName() + " failed", + e); + } + String vmName = vm.getVmName(); + /* should become a single entity */ + this._vmStats.remove(vmName); + } + + /* + * TODO: The actual VM provisioning start to end, we can rip this from our + * simple stuff + */ + @Override + public synchronized StartAnswer execute(StartCommand cmd) { + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + State state = State.Stopped; + Xen xen = new Xen(c); + + try { + synchronized (this._vmstates) { + this._vmstates.put(vmName, State.Starting); + } + Xen.Vm vm = xen.getVmConfig(); + /* max and min ? */ + vm.setVmCpus(vmSpec.getCpus()); + /* in mb not in bytes */ + vm.setVmMemory(vmSpec.getMinRam() / 1024 / 1024); + vm.setVmUuid(UUID.nameUUIDFromBytes(vmSpec.getName().getBytes()) + .toString()); + vm.setVmName(vmName); + String domType = Ovm3Helper.getOvm3GuestType(vmSpec.getOs()); + if (domType == null || domType.equals("")) { + domType = "default"; + s_logger.debug("VM Virt type missing setting to: " + domType); + } else { + s_logger.debug("VM Virt type set to " + domType + " for " + + vmSpec.getOs()); + } + vm.setVmDomainType(domType); + /* only for none user VMs? */ + vm.setVmExtra(vmSpec.getBootArgs().replace(" ", "%")); + + /* TODO: booting from CD... */ + if (vmSpec.getBootloader() == BootloaderType.CD) { + // do something with this please... + } + /* + * officially CD boot is only supported on HVM, although there is a + * simple way around it.. + */ + /* TODO: pool uuid now comes from here should change! */ + createVbds(vm, vmSpec); + + if (vmSpec.getType() != VirtualMachine.Type.User) { + String svmPath = _ovmRepo + "/" + + _ovmObject.deDash(vm.getPrimaryPoolUuid()) + "/ISOs"; + String svmIso = svmPath + "/" + + getSystemVMIsoFileNameOnDatastore(); + vm.addIso(svmIso); + } + /* TODO: OVS should go here! */ + createVifs(vm, vmSpec); + + /* vm migration requires a 0.0.0.0 bind */ + vm.setVncPassword(vmSpec.getVncPassword()); + vm.setVncAddress("0.0.0.0"); + vm.setVnc(); + + /* this should be getVmRootDiskPoolId ? */ + xen.createVm(_ovmObject.deDash(vm.getPrimaryPoolUuid()), + vm.getVmUuid()); + xen.startVm(_ovmObject.deDash(vm.getPrimaryPoolUuid()), + vm.getVmUuid()); + state = State.Running; + + if (vmSpec.getType() != VirtualMachine.Type.User) { + String controlIp = null; + for (NicTO nic : vmSpec.getNics()) { + if (nic.getType() == TrafficType.Control) { + controlIp = nic.getIp(); + } + } + + try { + CloudStackPlugin cSp = new CloudStackPlugin(c); + for (int count = 0; count < 60; count++) { + Boolean res = cSp.domrCheckSsh(controlIp); + s_logger.debug("connected to " + controlIp + + " on attempt " + count + " result: " + res); + Thread.sleep(5000); + if (res) { + break; + } + /* + * Older xend issues in, took me a while to figure this + * out: + * ../xen/xend/XendConstants.py + * """Minimum time between domain restarts in seconds.""" + * MINIMUM_RESTART_TIME = 60 + * this does NOT work!!!--^^ as we respawn within 30 + * seconds easily. + * return state stopped. + */ + if (_vmstates.get(vmName) == null) { + String msg = "VM " + vmName + " went missing on " + + _host + ", returning stopped"; + s_logger.debug(msg); + state = State.Stopped; + return new StartAnswer(cmd, msg); + } + } + } catch (Exception x) { + s_logger.debug("unable to connect to " + controlIp + " " + + x.getMessage()); + } + } + /* + * TODO: Can't remember if HA worked if we were only a pool ? + */ + if (_ovm3pool && _ovm3cluster) { + xen.configureVmHa(_ovmObject.deDash(vm.getPrimaryPoolUuid()), + vm.getVmUuid(), + true); + } + /* should be starting no ? */ + state = State.Running; + return new StartAnswer(cmd); + } catch (Exception e) { + s_logger.debug("Start vm " + vmName + " failed", e); + state = State.Stopped; + // cleanup(vmDetails); + return new StartAnswer(cmd, e.getMessage()); + } finally { + synchronized (this._vmstates) { + // FIXME: where to come to Stopped??? + this._vmstates.put(vmName, state); + } + } + } + + /* split out domr stuff later */ + private GetDomRVersionAnswer execute(GetDomRVersionCmd cmd) { + String args = this.DefaultDomRPath + "get_template_version.sh"; + String ip = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + try { + CloudStackPlugin cSp = new CloudStackPlugin(c); + CloudStackPlugin.ReturnCode result; + result = cSp.domrExec(ip, args); + if (!result.getRc() || result.getStdOut().isEmpty()) { + return new GetDomRVersionAnswer(cmd, "getDomRVersionCmd failed"); + } + String domResp = result.getStdOut(); + String[] lines = domResp.split("&"); + if (lines.length != 2) { + return new GetDomRVersionAnswer(cmd, domResp); + } + return new GetDomRVersionAnswer(cmd, domResp, lines[0], lines[1]); + } catch (Exception e) { + return new GetDomRVersionAnswer(cmd, "getDomRVersionCmd " + + e.getMessage()); + } + } + + private Answer giveDomRAns(Command cmd, String ip, String args, String resp) { + CloudStackPlugin cSp = new CloudStackPlugin(c); + try { + CloudStackPlugin.ReturnCode result = cSp.domrExec(ip, args); + if (!result.getRc()) { + return new Answer(cmd, false, result.getStdOut()); + } + } catch (Exception e) { + return new Answer(cmd, false, e.getMessage()); + } + return new Answer(cmd); + } + + protected synchronized Answer execute(final DhcpEntryCommand cmd) { + String args = this.DefaultDomRPath + "edithosts.sh"; + String ip = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + if (cmd.getVmIpAddress() != null) { + args += " -4 " + cmd.getVmIpAddress(); + } + args += " -m " + cmd.getVmMac(); + args += " -n " + cmd.getVmName(); + if (cmd.getDefaultRouter() != null) { + args += " -d " + cmd.getDefaultRouter(); + } + if (cmd.getStaticRoutes() != null) { + args += " -s " + cmd.getStaticRoutes(); + } + + if (cmd.getDefaultDns() != null) { + args += " -N " + cmd.getDefaultDns(); + } + + if (cmd.getVmIp6Address() != null) { + args += " -6 " + cmd.getVmIp6Address(); + args += " -u " + cmd.getDuid(); + } + + if (!cmd.isDefault()) { + args += " -z"; + } + + return giveDomRAns(cmd, ip, args, "DhcpEntry failed"); + } + + protected Answer execute(final SavePasswordCommand cmd) { + final String password = cmd.getPassword(); + final String ip = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + final String vmIpAddress = cmd.getVmIpAddress(); + String args = this.DefaultDomRPath + "savepassword.sh "; + args += " -v " + vmIpAddress; + args += " -p " + password; + return giveDomRAns(cmd, ip, args, "SavePassword failed"); + } + + protected Answer execute(final VmDataCommand cmd) { + String ip = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + Map<String, List<String[]>> data = new HashMap<String, List<String[]>>(); + data.put(cmd.getVmIpAddress(), cmd.getVmData()); + String json = new Gson().toJson(data); + json = Base64.encodeBase64String(json.getBytes()); + String args = this.DefaultDomRPath + "vmdata.py -d " + json; + return giveDomRAns(cmd, ip, args, "Set vm_data failed"); + } + + /* + * we don't for now, gave an error on migration though.... + */ + private Answer execute(NetworkRulesSystemVmCommand cmd) { + boolean success = true; + if (_canBridgeFirewall) { + // meh + } + return new Answer(cmd, success, ""); + } + + public CheckSshAnswer execute(CheckSshCommand cmd) { + String vmName = cmd.getName(); + String privateIp = cmd.getIp(); + int cmdPort = cmd.getPort(); + int interval = cmd.getInterval(); + int retries = cmd.getRetries(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying port " + privateIp + ":" + cmdPort); + } + try { + CloudStackPlugin cSp = new CloudStackPlugin(c); + if (!cSp.domrCheckPort(privateIp, cmdPort, retries, interval)) { + s_logger.info(vmName + ":" + cmdPort + " nok"); + return new CheckSshAnswer(cmd, "unable to connect"); + } + s_logger.info(vmName + ":" + cmdPort + " ok"); + } catch (Exception e) { + s_logger.error("Can not reach port on System vm " + vmName + + " due to exception", e); + return new CheckSshAnswer(cmd, e); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName + " " + + cmd); + } + if (VirtualMachineName.isValidRouterName(vmName)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Execute network usage setup command on " + + vmName); + } + // TODO: check this one out... + } + return new CheckSshAnswer(cmd); + } + + protected Answer execute(GetHostStatsCommand cmd) { + try { + CloudStackPlugin cSp = new CloudStackPlugin(c); + Map<String, String> stats = cSp.ovsDom0Stats(this._publicNetworkName); + Double cpuUtil = Double.parseDouble(stats.get("cpu")); + Double rxBytes = Double.parseDouble(stats.get("rx")); + Double txBytes = Double.parseDouble(stats.get("tx")); + Double totalMemory = Double.parseDouble(stats.get("total")); + Double freeMemory = Double.parseDouble(stats.get("free")); + HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), + cpuUtil, rxBytes, txBytes, "host", totalMemory, freeMemory, + 0, 0); + return new GetHostStatsAnswer(cmd, hostStats); + } catch (Exception e) { + s_logger.debug("Get host stats of " + cmd.getHostName() + " failed", + e); + return new Answer(cmd, false, e.getMessage()); + } + } + + /* TODO: Stop the VM, this means cleanup too, should this be destroy ? */ + @Override + public StopAnswer execute(StopCommand cmd) { + String vmName = cmd.getVmName(); + State state = State.Error; + synchronized (this._vmstates) { + state = _vmstates.get(vmName); + this._vmstates.put(vmName, State.Stopping); + } + + try { + Xen vms = new Xen(c); + Xen.Vm vm = null; + vm = vms.getRunningVmConfig(vmName); + + if (vm == null) { + state = State.Stopping; + s_logger.debug("Unable to get details of vm: " + vmName + + ", treating it as Stopping"); + return new StopAnswer(cmd, "success", true); + } + String repoId = _ovmObject.deDash(vm.getVmRootDiskPoolId()); + String vmId = vm.getVmUuid(); + + /* can we do without the poolId ? */ + vms.stopVm(repoId, vmId); + int tries = 30; + while (vms.getRunningVmConfig(vmName) != null && tries > 0) { + String msg = "Waiting for " + vmName + " to stop"; + s_logger.debug(msg); + tries--; + Thread.sleep(10 * 1000); + } + vms.deleteVm(repoId, vmId); + /* TODO: Check cleanup */ + this.cleanup(vm); + + if (vms.getRunningVmConfig(vmName) != null) { + String msg = "Stop " + vmName + " failed "; + s_logger.debug(msg); + return new StopAnswer(cmd, msg, false); + } + state = State.Stopped; + return new StopAnswer(cmd, "success", true); + } catch (Exception e) { + /* TODO: check output of message, might be that it did get removed */ + s_logger.debug("Stop " + vmName + " failed ", e); + return new StopAnswer(cmd, e.getMessage(), false); + } finally { + synchronized (this._vmstates) { + if (state != null) { + this._vmstates.put(vmName, state); + } else { + this._vmstates.remove(vmName); + } + } + } + } + + /* Reboot the VM and destroy should call the same method in here ? */ + @Override + public RebootAnswer execute(RebootCommand cmd) { + String vmName = cmd.getVmName(); + + synchronized (this._vmstates) { + this._vmstates.put(vmName, State.Starting); + } + + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getRunningVmConfig(vmName); + /* TODO: stop, start or reboot, reboot for now ? */ + xen.rebootVm(_ovmObject.deDash(vm.getVmRootDiskPoolId()), + vm.getVmUuid()); + vm = xen.getRunningVmConfig(vmName); + /* erh but this don't work, should point at cloudstackplugin */ + Integer vncPort = vm.getVncPort(); + return new RebootAnswer(cmd, null, vncPort); + } catch (Exception e) { + s_logger.debug("Reboot " + vmName + " failed", e); + return new RebootAnswer(cmd, e.getMessage(), false); + } finally { + synchronized (this._vmstates) { + this._vmstates.put(cmd.getVmName(), State.Running); + } + } + } + + protected State convertPowerToState(PowerState ps) { + final State state = s_stateMaps.get(ps.toString()); + return state == null ? State.Unknown : state; + } + + private static PowerState convertStateToPower(State s) { + final PowerState state = s_powerStateMaps.get(s.toString()); + return state == null ? PowerState.PowerUnknown : state; + } + + /* State to power in the states */ + protected Map<String, HostVmStateReportEntry> HostVmStateReport() + throws XmlRpcException { + final HashMap<String, HostVmStateReportEntry> vmStates = new HashMap<String, HostVmStateReportEntry>(); + Map<String, State> vms = sync(); + for (final Map.Entry<String, State> vm : vms.entrySet()) { + /* TODO: Figure out how to get xentools version in here */ + s_logger.debug("VM " + vm.getKey() + " state: " + vm.getValue() + + ":" + convertStateToPower(vm.getValue())); + vmStates.put(vm.getKey(), new HostVmStateReportEntry( + convertStateToPower(vm.getValue()), c.getIp(), null)); + } + return vmStates; + } + + /* uses the running configuration, not the vm.cfg configuration */ + protected Map<String, Xen.Vm> getAllVms() throws XmlRpcException { + try { + Xen vms = new Xen(c); + return vms.getRunningVmConfigs(); + } catch (Exception e) { + s_logger.debug("getting VM list from " + _host + " failed", e); + throw new CloudRuntimeException("Exception on getting VMs from " + + _host + ":" + e.getMessage(), e); + } + } + + /* + * Get all the states and set them up according to xm(1) + * TODO: check migrating ? + */ + protected HashMap<String, State> getAllVmStates() throws XmlRpcException { + Map<String, Xen.Vm> vms = getAllVms(); + final HashMap<String, State> states = new HashMap<String, State>(); + for (final Map.Entry<String, Xen.Vm> entry : vms.entrySet()) { + Xen.Vm vm = entry.getValue(); + if (vm.isControlDomain()) { + continue; + } + State ns = State.Running; + String as = vm.getVmState(); + /* missing VM is stopped */ + if (as == null) { + ns = State.Stopped; + continue; + } + /* The domain is currently running on a CPU */ + /* need a more exact match! */ + if (as.contains("r")) { + ns = State.Running; + /* The domain is blocked, and not running or runnable. */ + } else if (as.contains("b")) { + ns = State.Running; + /* The domain has been paused */ + } else if (as.contains("p")) { + ns = State.Running; + /* The guest has requested to be shutdown, still migrating... */ + } else if (as.contains("s")) { + if (this._vmstates.get(vm.getVmName()) == State.Migrating) + ns = State.Migrating; + ns = State.Stopped; + /* The domain has crashed */ + } else if (as.contains("c")) { + ns = State.Error; + /* + * The domain is in process of dying (if we see this twice we + * have a problem ?) + */ + } else if (as.contains("d")) { + ns = State.Stopping; + } else { + ns = State.Unknown; + } + s_logger.debug("state " + ns + " for " + vm.getVmName() + + " based on " + as); + states.put(vm.getVmName(), ns); + } + return states; + } + + /* sync the state we know of with reality */ + protected HashMap<String, State> sync() { + HashMap<String, State> newStates; + HashMap<String, State> oldStates = null; + + try { + final HashMap<String, State> changes = new HashMap<String, State>(); + newStates = getAllVmStates(); + if (newStates == null) { + s_logger.debug("Unable to get the vm states so no state sync at this point."); + return null; + } + + synchronized (_vmstates) { + oldStates = new HashMap<String, State>(_vmstates.size()); + oldStates.putAll(_vmstates); + + for (final Map.Entry<String, State> entry : newStates + .entrySet()) { + final String vmName = entry.getKey(); + State newState = entry.getValue(); + final State oldState = oldStates.remove(vmName); + s_logger.debug("state for " + vmName + ", old: " + oldState + + ", new: " + newState); + + /* eurh ? */ + if (newState == State.Stopped && oldState != State.Stopping + && oldState != null && oldState != State.Stopped) { + s_logger.debug("Getting power state...."); + newState = State.Running; + } + + if (s_logger.isTraceEnabled()) { + s_logger.trace("VM " + + vmName + + ": ovm has state " + + newState + + " and we have state " + + (oldState != null ? oldState.toString() + : "null")); + } + + /* TODO: is this really true ? should be right ? */ + if (newState == State.Migrating) { + s_logger.debug(vmName + + " is migrating, skipping state check"); + continue; + } + + if (oldState == null) { + _vmstates.put(vmName, newState); + s_logger.debug("New state without old state: " + vmName); + changes.put(vmName, newState); + } else if (oldState == State.Starting) { + if (newState == State.Running) { + _vmstates.put(vmName, newState); + } else if (newState == State.Stopped) { + s_logger.debug("Ignoring vm " + vmName + + " because of a lag in starting the vm."); + } + } else if (oldState == State.Migrating) { + if (newState == State.Running) { + s_logger.debug("Detected that a migrating VM is now running: " + + vmName); + _vmstates.put(vmName, newState); + } + } else if (oldState == State.Stopping) { + if (newState == State.Stopped) { + _vmstates.put(vmName, newState); + } else if (newState == State.Running) { + s_logger.debug("Ignoring vm " + vmName + + " because of a lag in stopping the vm. "); + } + } else if (oldState != newState) { + _vmstates.put(vmName, newState); + if (newState == State.Stopped) { + // TODO: need to state.error here ? + } + changes.put(vmName, newState); + } + } + + for (final Map.Entry<String, State> entry : oldStates + .entrySet()) { + final String vmName = entry.getKey(); + final State oldState = entry.getValue(); + + if (oldState == State.Stopping) { + s_logger.debug("Removing VM " + vmName + + " in transition state stopping."); + _vmstates.remove(vmName); + } else if (oldState == State.Starting) { + s_logger.debug("Removing VM " + vmName + + " in transition state starting."); + _vmstates.remove(vmName); + } else if (oldState == State.Stopped) { + s_logger.debug("Stopped VM " + vmName + " removing."); + _vmstates.remove(vmName); + } else if (oldState == State.Migrating) { + /* + * do something smarter here.. newstate should + * say stopping already + */ + s_logger.debug("Ignoring VM " + vmName + + " in migrating state."); + } else { + /* if it's not there name it stopping */ + _vmstates.remove(vmName); + State state = State.Stopping; + s_logger.debug("VM " + + vmName + + " is now missing from ovm3 server so removing it"); + /* TODO: something about killed/halted VM's in here ? */ + changes.put(vmName, state); + } + } + } + + return changes; + } catch (Exception e) { + s_logger.debug("Ovm3 full sync failed", e); + return null; + } + } + + /* cleanup the storageplugin so we can use an object here */ + protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { + // cmd.getStorageId(); + s_logger.debug("Getting stats for: " + cmd.getStorageId()); + try { + Linux host = new Linux(c); + /* TODO: NFS only for now */ + Map<String, Linux.FileSystem> fsList = host + .getFileSystemList("nfs"); + Linux.FileSystem fs = fsList.get(cmd.getStorageId()); + StoragePlugin store = new StoragePlugin(c); + /* + * TODO: something odd here where do I get which Storage I need to + * look at ? + */ + String propUuid = store.deDash(cmd.getStorageId()); + String mntUuid = cmd.getStorageId(); + store.setUuid(propUuid); + store.setSsUuid(propUuid); + store.setMntUuid(mntUuid); + store.setFsHost(fs.getHost()); + store.setFsSourcePath(fs.getDevice()); + store.storagePluginGetFileSystemInfo(); + long total = Long.parseLong(store.getTotalSize()); + long used = total - Long.parseLong(store.getFreeSize()); + return new GetStorageStatsAnswer(cmd, total, used); + } catch (Exception e) { + s_logger.debug("GetStorageStatsCommand on pool " + + cmd.getStorageId() + " failed", + e); + return new GetStorageStatsAnswer(cmd, e.getMessage()); + } + } + + private VmStatsEntry getVmStat(String vmName) throws XmlRpcException { + CloudStackPlugin cSp = new CloudStackPlugin(c); + Map<String, String> stats = cSp.ovsDomUStats(vmName); + Map<String, String> o_stats = this._vmStats.get(vmName); + VmStatsEntry e = new VmStatsEntry(); + if (o_stats == null) { + e.setNumCPUs(1); + e.setNetworkReadKBs(0); + e.setNetworkWriteKBs(0); + e.setDiskReadKBs(0); + e.setDiskWriteKBs(0); + e.setDiskReadIOs(0); + e.setDiskWriteIOs(0); + e.setCPUUtilization(0); + e.setEntityType("vm"); + } else { + /* beware of negatives ? */ + Integer cpus = Integer.parseInt(stats.get("vcpus")); + e.setNumCPUs(Integer.parseInt(stats.get(cpus))); + e.setNetworkReadKBs(Double.parseDouble(stats.get("rx_bytes")) + - Double.parseDouble(o_stats.get("rx_bytes"))); + e.setNetworkWriteKBs(Double.parseDouble(stats.get("tx_bytes")) + - Double.parseDouble(o_stats.get("tx_bytes")));; + e.setDiskReadKBs(Double.parseDouble(stats.get("rd_bytes")) + - Double.parseDouble(o_stats.get("rd_bytes")));; + e.setDiskWriteKBs(Double.parseDouble(stats.get("rw_bytes")) + - Double.parseDouble(o_stats.get("rw_bytes"))); + e.setDiskReadIOs(Double.parseDouble(stats.get("rd_ops")) + - Double.parseDouble(o_stats.get("rd_ops"))); + e.setDiskWriteIOs(Double.parseDouble(stats.get("rw_ops")) + - Double.parseDouble(o_stats.get("rw_ops"))); + + Double d_cpu = Double.parseDouble(stats.get("cputime")) + - Double.parseDouble(o_stats.get("cputime")); + Double d_time = Double.parseDouble(stats.get("uptime")) + - Double.parseDouble(o_stats.get("uptime")); + Double cpupct = d_cpu/d_time * 100 * cpus; + e.setCPUUtilization(cpupct); + e.setEntityType("vm"); + } + this._vmStats.replace(vmName, stats); + return e; + } + + /* TODO: The main caller for vm statstics */ + protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) { + List<String> vmNames = cmd.getVmNames(); + HashMap<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>(); + for (String vmName : vmNames) { + try { + VmStatsEntry e = getVmStat(vmName); + vmStatsNameMap.put(vmName, e); + } catch (XmlRpcException e) { + s_logger.debug("Get vm stat for " + vmName + " failed", e); + continue; + } + } + return new GetVmStatsAnswer(cmd, vmStatsNameMap); + } + + /* TODO: Hot plugging harddisks... */ + protected AttachVolumeAnswer execute(AttachVolumeCommand cmd) { + return new AttachVolumeAnswer(cmd, "You must stop " + cmd.getVmName() + + " first, OVM doesn't support hotplug datadisk"); + } + + /* Destroy a volume (image) */ + public Answer execute(DestroyCommand cmd) { + VolumeTO vol = cmd.getVolume(); + String vmName = cmd.getVmName(); + try { + StoragePlugin store = new StoragePlugin(c); + // TODO: check if path is correct... + store.storagePluginDestroy(vol.getPoolUuid(), vol.getPath()); + return new Answer(cmd, true, "Success"); + } catch (Exception e) { + s_logger.debug("Destroy volume " + vol.getName() + " failed for " + + vmName + " ", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + /* Migration should make sure both HVs are the same ? */ + protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) { + VirtualMachineTO vm = cmd.getVirtualMachine(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Preparing host for migrating " + vm.getName()); + } + /* securitygroups */ + try { + synchronized (_vmstates) { + _vmstates.put(vm.getName(), State.Migrating); + } + return new PrepareForMigrationAnswer(cmd); + } catch (Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + + " prepare for migration failed due to " + e.toString(), e); + return new PrepareForMigrationAnswer(cmd, e); + } + } + + /* do migrations of VMs in a simple way just inside a cluster for now */ + protected MigrateAnswer execute(final MigrateCommand cmd) { + final String vmName = cmd.getVmName(); + String destUuid = cmd.getHostGuid(); + String destIp = cmd.getDestinationIp(); + State state = State.Error; + /* + * TODO: figure out non pooled migration, works from CLI but not from + * the agent... perhaps pause the VM and then migrate it ? for now + * just stop the VM. + */ + String msg = "Migrating " + vmName + " to " + destIp; + s_logger.info(msg); + if (!this._ovm3cluster && !this._ovm3pool) { + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getRunningVmConfig(vmName); + HostVO destHost = _resourceMgr.findHostByGuid(destUuid); + if (destHost == null) { + msg = "Unable to find migration target host in DB " + + destUuid + " with ip " + destIp; + s_logger.info(msg); + return new MigrateAnswer(cmd, false, msg, null); + } + xen.stopVm(_ovmObject.deDash(vm.getVmRootDiskPoolId()), + vm.getVmUuid()); + msg = destHost.toString(); + state = State.Stopping; + return new MigrateAnswer(cmd, false, msg, null); + } catch (Exception e) { + msg = "Unpooled VM Migrate of " + vmName + " to " + destUuid + + " failed due to: " + e.getMessage(); + s_logger.debug(msg, e); + return new MigrateAnswer(cmd, false, msg, null); + } finally { + /* shouldn't we just reinitialize completely as a last resort ? */ + synchronized (_vmstates) { + _vmstates.put(vmName, state); + } + } + } else { + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getRunningVmConfig(vmName); + if (vm == null) { + state = State.Stopped; + msg = vmName + " is no running on " + _host; + return new MigrateAnswer(cmd, false, msg, null); + } + /* not a storage migration!!! */ + xen.migrateVm(_ovmObject.deDash(vm.getVmRootDiskPoolId()), + vm.getVmUuid(), + destIp); + state = State.Stopping; + msg = "Migration of " + vmName + " successfull"; + return new MigrateAnswer(cmd, true, msg, null); + } catch (Exception e) { + msg = "Pooled VM Migrate" + ": Migration of " + vmName + " to " + + destIp + " failed due to " + e.getMessage(); + s_logger.debug(msg, e); + return new MigrateAnswer(cmd, false, msg, null); + } finally { + /* if (state != state.Stopped) { */ + synchronized (_vmstates) { + _vmstates.put(vmName, state); + } + } + } + } + + /* hHeck "the" virtual machine */ + protected CheckVirtualMachineAnswer execute( + final CheckVirtualMachineCommand cmd) { + String vmName = cmd.getVmName(); + try { + // if state migrating skip ? + Xen vms = new Xen(c); + Xen.Vm vm = vms.getRunningVmConfig(vmName); + /* check if there is a VM */ + + CloudStackPlugin plug = new CloudStackPlugin(c); + Integer vncPort = Integer.valueOf(plug.getVncPort(vmName)); + if (vncPort == 0) { + s_logger.warn("No VNC port for " + vmName); + } + /* we already have the state ftw */ + Map<String, State> states = getAllVmStates(); + State vmState = states.get(vmName); + if (vmState == null) { + s_logger.warn("Check state of " + vmName + + " return null in CheckVirtualMachineCommand"); + vmState = State.Stopped; + } + synchronized (_vmstates) { + _vmstates.put(vmName, State.Running); + } + return new CheckVirtualMachineAnswer(cmd, vmState, vncPort); + } catch (Exception e) { + s_logger.debug("Check migration for " + vmName + " failed", e); + return new CheckVirtualMachineAnswer(cmd, State.Stopped, null); + } + } + + /* TODO: fill this one, for maintenance */ + protected MaintainAnswer execute(MaintainCommand cmd) { + /* leave cluster, leave pool, release ownership ? */ + try { + Network net = new Network(c); + Pool pool = new Pool(c); + // pool.leaveServerPool(); + net.stopOvsLocalConfig(_controlNetworkName); + } catch (Exception e) { + s_logger.debug("unable to disable " + _controlNetworkName); + } + return new MaintainAnswer(cmd); + } + + /* + */ + protected GetVncPortAnswer execute(GetVncPortCommand cmd) { + try { + Xen host = new Xen(c); + Xen.Vm vm = host.getRunningVmConfig(cmd.getName()); + Integer vncPort = vm.getVncPort(); + s_logger.debug("get vnc port for " + cmd.getName() + ": " + vncPort); + return new GetVncPortAnswer(cmd, _ip, vncPort); + } catch (Exception e) { + s_logger.debug("get vnc port for " + cmd.getName() + " failed", e); + return new GetVncPortAnswer(cmd, e.getMessage()); + } + } + + protected Answer execute(PingTestCommand cmd) { + try { + if (cmd.getComputingHostIp() != null) { + CloudStackPlugin cSp = new CloudStackPlugin(c); + if (!cSp.ping(cmd.getComputingHostIp())) { + return new Answer(cmd, false, "ping failed"); + } + } else { + return new Answer(cmd, false, "why asks me to ping router???"); + } + return new Answer(cmd, true, "success"); + } catch (Exception e) { + s_logger.debug("Ping " + cmd.getComputingHostIp() + " failed", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + /* + * TODO: no heartbeat if no cluster, should we add a heartbeat ? + * cloudstack/plugins + * /hypervisors/ovm/scripts/vm/hypervisor/ovm/OvmHostModule.py contains + * fence + */ + protected FenceAnswer execute(FenceCommand cmd) { + try { + Boolean res = false; + return new FenceAnswer(cmd, res, res.toString()); + } catch (Exception e) { + s_logger.debug("fence " + cmd.getHostIp() + " failed", e); + return new FenceAnswer(cmd, false, e.getMessage()); + } + } + + /* TODO: nothing yet */ + protected boolean canBridgeFirewall() throws XmlRpcException { + return false; + } + + protected boolean prepareForPool() throws ConfigurationException { + /* need single master uuid */ + try { + Linux host = new Linux(c); + Pool pool = new Pool(c); + + /* setup pool and role, needs utility to be able to do things */ + if (host.getServerRoles().contentEquals(pool.getValidRoles() + .toString())) { + s_logger.debug("Server role for host " + _host + " is ok"); + } else { + try { + pool.setServerRoles(pool.getValidRoles()); + } catch (Exception e) { + s_logger.debug("Failed to set server role for host " + + _host, e); + throw new ConfigurationException( + "Unable to set server role for host"); + } + } + if (host.getMembershipState().contentEquals("Unowned")) { + try { + s_logger.debug("Take ownership of host " + _host); + pool.takeOwnership(_masterUuid, ""); + } catch (Exception e) { + String msg = "Failed to take ownership of host " + _host; + s_logger.debug(msg, e); + throw new ConfigurationException(msg); + } + } else { + /* TODO: check if it's part of our pool, give ok if it is */ + if (host.getManagerUuid().equals(_masterUuid)) { + String msg = "Host " + _host + " owned by us"; + s_logger.debug(msg); + return true; + } else { + String msg = "Host " + _host + + " already part of a pool, and not owned by us"; + s_logger.debug(msg); + throw new ConfigurationException(msg); + } + } + } catch (Exception es) { + String msg = "Failed to prepare " + _host + " for pool"; + s_logger.debug(msg, es); + throw new ConfigurationException(msg + ": " + es.getMessage()); + } + return true; + } + + /* + * TODO: redo this, it's a mess now. + */ + protected Boolean setupPool(StorageFilerTO cmd) + throws ConfigurationException, XmlRpcException, Exception { + String primUuid = cmd.getUuid(); + String ssUuid = _ovmObject.deDash(primUuid); + String ovsRepo = this._ovmRepo + "/" + _ovmObject.deDash(primUuid); + String fsType = "nfs"; + /* TODO: 16, need to get this from the cluster id actually */ + String clusterUuid = _masterUuid.substring(0, 15); + String managerId = _masterUuid; + String poolAlias = cmd.getHost() + ":" + cmd.getPath(); + String mountPoint = String.format("%1$s:%2$s", + cmd.getHost(), + cmd.getPath()) + + "/VirtualMachines"; + List<String> members = new ArrayList<String>(); + _isMaster = masterCheck(); + Integer poolSize = 0; + String msg = ""; + + try { + Pool poolHost = new Pool(c); + if (_isMaster && !poolHost.getPoolId().contentEquals(primUuid) + && !_hasMaster) { + PoolOCFS2 poolFs = new PoolOCFS2(c); + try { + try { + msg = "Create poolfs on " + _host + " for repo " + + primUuid; + s_logger.debug(msg); + poolFs.createPoolFs(fsType, + mountPoint, + clusterUuid, + primUuid, + ssUuid, + managerId, + primUuid); + } catch (Exception e) { + msg = "Poolfs already exists on " + _host + + " for repo " + primUuid; + s_logger.debug(msg); + } + try { + poolHost.createServerPool(poolAlias, + primUuid, + _ovm3vip, + poolSize + 1, + _host, + _ip); + } catch (Exception e) { + msg = "Server pool with id " + clusterUuid + " on " + + _host; + s_logger.debug(msg); + } + } catch (Exception e) { + msg = "Failed to create pool on " + _host + " for repo " + + primUuid; + s_logger.debug(msg, e); + throw new Exception(msg); + } + } else if (!_isMaster || _hasMaster) { + Pool poolMaster = new Pool(m); + poolSize = poolMaster.getPoolMemberIpList().size() + 1; + members.addAll(poolMaster.getPoolMemberIpList()); + + poolHost = new Pool(c); + if (!poolHost.getPoolId().contentEquals(primUuid)) { + + /* get all the details from the master */ + try { + /* why does it call bloody M here???!?!?!! */ + poolHost.joinServerPool(poolAlias, + primUuid, + _ovm3vip, + poolSize, + _host, + _ip); + } catch (Exception e) { + msg = "Failed to join server pool " + + poolMaster.getPoolAlias() + " on " + _host + + " for pool " + primUuid; + s_logger.debug(msg, e); + throw new Exception(msg); + } + } + } else { + s_logger.debug("Pool " + primUuid + " already configured on " + + _host); + } + if (!members.contains(_ip)) { + members.add(_ip); + } + for (String member : members) { + /* easy way out for now..., should get this from hostVO */ + String url = "http://" + this._agentUserName + ":" + + this._agentPassword + "@" + member + ":" + _agentPort + + "/api/3"; + /* + * Common comCall = new Common(c); + * comCall.dispatch(url, + * "set_pool_member_ip_list", + * StringUtils.join(members, ",")); + */ + Connection x = new Connection(member, _agentPort, + _agentUserName, _agentPassword); + Pool xpool = new Pool(x); + xpool.setPoolIps(members); + xpool.setPoolMemberIpList(); + msg = "Added " + member + " to pool " + primUuid; + s_logger.debug(msg); + } + } catch (Exception e) { + msg = "Failed to setup server pool on " + _host; + s_logger.debug(msg, e); + throw new Exception(msg); + } + return true; + } + + /* the storage url combination of host and path is unique */ + protected String setupSecondaryStorage(String url) throws Exception { + URI uri = URI.create(url); + String uuid = _ovmObject.newUuid(uri.getHost() + ":" + uri.getPath()); + s_logger.info("Secondary storage with uuid: " + uuid); + return setupNfsStorage(uri, uuid); + } + + protected String setupNfsStorage(URI uri, String uuid) throws Exception { + String fsUri = "nfs"; + String fsType = "FileSys"; + String msg = ""; + String mountPoint = this._ovmSec + "/" + uuid; + Linux host = new Linux(c); + try { + Map<String, Linux.FileSystem> fsList = host + .getFileSystemList(fsUri); + Linux.FileSystem fs = fsList.get(uuid); + if (fs == null || !fs.getMountPoint().equals(mountPoint)) { + try { + StoragePlugin sp = new StoragePlugin(c); + sp.storagePluginMount(uri.getHost(), + uri.getPath(), + uuid, + mountPoint); + msg = "Nfs storage " + uri + " mounted on " + mountPoint; + return uuid; + } catch (Exception ec) { + msg = "Nfs storage " + uri + " mount on " + mountPoint + + " FAILED " + ec.getMessage(); + throw new Exception(msg, ec); + } + } else { + msg = "NFS storage " + uri + " already mounted on " + + mountPoint; + return uuid; + } + } finally { + s_logger.debug(msg); + } + } + + /* TODO: move the connection elsewhere.... */ + protected boolean masterCheck() throws ConfigurationException, Exception { + if (_ovm3vip.equals("")) { + s_logger.debug("No cluster vip, not checking for master"); + return false; + } + try { + /* should get the details of that host hmmz */ + m = new Connection(_ovm3vip, _agentPort, _agentUserName, + _agentPassword); + Linux master = new Linux(m); + if (master.getHostName().equals(_host)) { + s_logger.debug("Host " + _host + " is master"); + this._isMaster = true; + } else { + s_logger.debug("Host " + _host + " has master " + + master.getHostName()); + _hasMaster = true; + } + } catch (Exception e) { + this._isMaster = true; + s_logger.debug("Unable to connect to master, we are master"); + } finally { + if (!this._isMaster) { + if (this._hasMaster) { + s_logger.debug("Host " + _host + " will become a slave " + + _ovm3vip); + return this._isMaster; + } else { + this._isMaster = true; + s_logger.debug("Host " + _host + " will become a master " + + _ovm3vip); + return this._isMaster; + } + } + } + return this._isMaster; + } + + /* check if a VM is running should be added */ + protected CreatePrivateTemplateAnswer execute( + final CreatePrivateTemplateFromVolumeCommand cmd) { + String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); + String volumePath = cmd.getVolumePath(); + Long accountId = cmd.getAccountId(); + Long templateId = cmd.getTemplateId(); + int wait = cmd.getWait(); + if (wait == 0) { + /* Defaut timeout 2 hours */ + wait = 7200; + } + + try { + URI uri; + uri = new URI(secondaryStorageUrl); + String secondaryStorageMountPath = uri.getHost() + ":" + + uri.getPath(); + /* missing uuid */ + String installPath = _ovmRepo + "/Templates/" + accountId + "/" + + templateId; + String templateLoc = installPath; + Linux host = new Linux(c); + /* check if VM is running or thrown an error, or pause it :P */ + host.copyFile(volumePath, installPath); + /* TODO: look at the original */ + return new CreatePrivateTemplateAnswer(cmd, true, installPath); + /* + * res.get("installPath"), Long.valueOf(res.get("virtualSize")), + * Long.valueOf(res.get("physicalSize")), + * res.get("templateFileName"), ImageFormat.RAW); + */ + } catch (Exception e) { + s_logger.debug("Create template failed", e); + return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage()); + } + } + + /* + * Might have some logic errors that's what debugging is for... + */ + protected CopyVolumeAnswer execute(CopyVolumeCommand cmd) { + String volumePath = cmd.getVolumePath(); + /* is a repository */ + String secondaryStorageURL = cmd.getSecondaryStorageURL(); + int wait = cmd.getWait(); + if (wait == 0) { + wait = 7200; + } + + /* TODO: we need to figure out what sec and prim really is */ + try { + Linux host = new Linux(c); + + /* to secondary storage */ + if (cmd.toSecondaryStorage()) { + s_logger.debug("Copy to secondary storage " + volumePath + + " to " + secondaryStorageURL); + host.copyFile(volumePath, secondaryStorageURL); + /* from secondary storage */ + } else { + s_logger.debug("Copy from secondary storage " + + secondaryStorageURL + " to " + volumePath); + host.copyFile(secondaryStorageURL, volumePath); + } + /* check the truth of this */ + return new CopyVolumeAnswer(cmd, true, null, null, null); + } catch (Exception e) { + s_logger.debug("Copy volume failed", e); + return new CopyVolumeAnswer(cmd, false, e.getMessage(), null, null); + } + } + + /* + * TODO: this ties into if we're in a cluster or just a pool, leaving a pool + * means just leaving the pool and getting rid of the pooled fs, different a + * repo though + */ + protected Answer execute(DeleteStoragePoolCommand cmd) { + try { + Pool pool = new Pool(c); + pool.leaveServerPool(cmd.getPool().getUuid()); + /* also connect to the master and update the pool list ? */ + } catch (Exception e) { + s_logger.debug("Delete storage pool on host " + + _host + + " failed, however, we leave to user for cleanup and tell managment server it succeeded", + e); + } + + return new Answer(cmd); + } + + /* TODO: check getPhysicalNetworkInfoList */ + /* + * need to refactor this bit, networksetupbyname makes no sense, and neither + * does the physical bit + */ + protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Checking if network name setup is done on " + _host); + } + + List<PhysicalNetworkSetupInfo> infoList = cmd + .getPhysicalNetworkInfoList(); + boolean errorout = false; + String msg = ""; + /* here we assume all networks are set */ + for (PhysicalNetworkSetupInfo info : infoList) { + if (info.getGuestNetworkName() == null) + info.setGuestNetworkName(this._guestNetworkName); + if (info.getPublicNetworkName() == null) + info.setPublicNetworkName(this._publicNetworkName); + if (info.getPrivateNetworkName() == null) + info.setPrivateNetworkName(this._privateNetworkName); + if (info.getStorageNetworkName() == null) + info.setStorageNetworkName(this._storageNetworkName); + + if (!isNetworkSetupByName(info.getGuestNetworkName())) { + msg = "For Physical Network id:" + + info.getPhysicalNetworkId() + + ", Guest Network is not configured on the backend by name " + + info.getGuestNetworkName(); + errorout = true; + break; + } + if (!isNetworkSetupByName(info.getPrivateNetworkName())) { + msg = "For Physical Network id:" + + info.getPhysicalNetworkId() + + ", Private Network is not configured on the backend by name " + + info.getPrivateNetworkName(); + errorout = true; + break; + } + if (!isNetworkSetupByName(info.getPublicNetworkName())) { + msg = "For Physical Network id:" + + info.getPhysicalNetworkId() + + ", Public Network is not configured on the backend by name " + + info.getPublicNetworkName(); + errorout = true; + break; + } + /* Storage network is optional, will revert to private otherwise */ + } + + if (errorout) { + s_logger.error(msg); + return new CheckNetworkAnswer(cmd, false, msg); + } else { + return new CheckNetworkAnswer(cmd, true, + "Network Setup check by names is done"); + } + } + + private boolean isNetworkSetupByName(String nameTag) { + s_logger.debug("known networks: " + this._guestNetworkName + " " + + this._publicNetworkName + " " + this._privateNetworkName); + if (nameTag != null) { + s_logger.debug("Looking for network setup by name " + nameTag); + + try { + Network net = new Network(c); + net.setBridgeList(_interfaces); + if (net.getBridgeByName(nameTag) != null) { + s_logger.debug("Found bridge with name: " + nameTag); + return true; + } + } catch (Exception e) { + s_logger.debug("Unxpected error looking for name: " + nameTag); + return false; + } + } + s_logger.debug("No bridge with name: " + nameTag); + return false; + } + + @Override + public Answer executeRequest(Command cmd) { + Class<? extends Command> clazz = cmd.getClass(); + if (clazz == ReadyCommand.class) { + return execute((ReadyCommand) cmd); + } else if (clazz == CopyCommand.class) { + return execute((CopyCommand) cmd); + } else if (clazz == DeleteCommand.class) { + return execute((DeleteCommand) cmd); + } else if (clazz == CreateStoragePoolCommand.class) { + return execute((CreateStoragePoolCommand) cmd); + } else if (clazz == ModifyStoragePoolCommand.class) { + return execute((ModifyStoragePoolCommand) cmd); + } else if (clazz == PrimaryStorageDownloadCommand.class) { + return execute((PrimaryStorageDownloadCommand) cmd); + } else if (clazz == CreateCommand.class) { + return execute((CreateCommand) cmd); + } else if (clazz == GetHostStatsCommand.class) { + return execute((GetHostStatsCommand) cmd); + } else if (clazz == StopCommand.class) { + return execute((StopCommand) cmd); + } else if (clazz == RebootCommand.class) { + return execute((RebootCommand) cmd); + } else if (clazz == GetStorageStatsCommand.class) { + return execute((GetStorageStatsCommand) cmd); + } else if (clazz == GetVmStatsCommand.class) { + return execute((GetVmStatsCommand) cmd); + } else if (clazz == AttachVolumeCommand.class) { + return execute((AttachVolumeCommand) cmd); + } else if (clazz == DestroyCommand.class) { + return execute((DestroyCommand) cmd); + } else if (clazz == PrepareForMigrationCommand.class) { + return execute((PrepareForMigrationCommand) cmd); + } else if (clazz == MigrateCommand.class) { + return execute((MigrateCommand) cmd); + } else if (clazz == CheckVirtualMachineCommand.class) { + return execute((CheckVirtualMachineCommand) cmd); + } else if (clazz == MaintainCommand.class) { + return execute((MaintainCommand) cmd); + } else if (clazz == StartCommand.class) { + return execute((StartCommand) cmd); + } else if (clazz == GetVncPortCommand.class) { + return execute((GetVncPortCommand) cmd); + } else if (clazz == PingTestCommand.class) { + return execute((PingTestCommand) cmd); + } else if (clazz == FenceCommand.class) { + return execute((FenceCommand) cmd); + } else if (clazz == AttachIsoCommand.class) { + return execute((AttachIsoCommand) cmd); + } else if (clazz == DettachCommand.class) { + return execute((DettachCommand) cmd); + } else if (clazz == AttachCommand.class) { + return execute((AttachCommand) cmd); + } else if (clazz == NetworkRulesSystemVmCommand.class) { + return execute((NetworkRulesSystemVmCommand) cmd); + /* + * } else if (clazz == SecurityGroupRulesCmd.class) { return + * execute((SecurityGroupRulesCmd) cmd); } else if (clazz == + * CleanupNetworkRulesCmd.class) { return + * execute((CleanupNetworkRulesCmd) cmd); } else if (clazz == + * PrepareOCFS2NodesCommand.class) { return + * execute((PrepareOCFS2NodesCommand) cmd); + */ + } else if (clazz == CreatePrivateTemplateFromVolumeCommand.class) { + return execute((CreatePrivateTemplateFromVolumeCommand) cmd); + } else if (clazz == CopyVolumeCommand.class) { + return execute((CopyVolumeCommand) cmd); + } else if (clazz == DeleteStoragePoolCommand.class) { + return execute((DeleteStoragePoolCommand) cmd); + } else if (clazz == CheckNetworkCommand.class) { + return execute((CheckNetworkCommand) cmd); + } else if (clazz == CheckSshCommand.class) { + return execute((CheckSshCommand) cmd); + } else if (clazz == GetDomRVersionCmd.class) { + return execute((GetDomRVersionCmd) cmd); + } else if (clazz == DhcpEntryCommand.class) { + return execute((DhcpEntryCommand) cmd); + } else if (clazz == SavePasswordCommand.class) { + return execute((SavePasswordCommand) cmd); + } else if (clazz == VmDataCommand.class) { + return execute((VmDataCommand) cmd); + } else if (clazz == CreateObjectCommand.class) { + return execute((CreateObjectCommand) cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } + + @Override + public void disconnected() { + // TODO Auto-generated method stub + + } + + @Override + public IAgentControl getAgentControl() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setAgentControl(IAgentControl agentControl) { + // TODO Auto-generated method stub + + } + + @Override + public void setName(String name) { + // TODO Auto-generated method stub + + } + + @Override + public void setConfigParams(Map<String, Object> params) { + // TODO Auto-generated method stub + + } + + @Override + public Map<String, Object> getConfigParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRunLevel() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setRunLevel(int level) { + // TODO Auto-generated method stub + + } + + /* TODO: move to the StoragPprocessor */ + @Override + public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer createTemplateFromVolume(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer createTemplateFromSnapshot(CopyCommand cmd) { + return null; // To change body of implemented methods use File | + // Settings | File Templates. + } + + @Override + public Answer backupSnapshot(CopyCommand cmd) { + return new Answer(cmd); + } + + /* + * TODO: Add iso and update config of the VM is done from set_disk in + * lib/xenxm.py (Example found in Xen.java) + * Iso first needs to be copied over to the primary storage where the ISOs + * reside, or just mount secondary storage, feh! + */ + protected Answer execute(AttachIsoCommand cmd) { + try { + URI iso = new URI(cmd.getIsoPath()); + String isoPath = iso.getHost() + ":" + iso.getPath(); + /* + * Ovm3Vm.detachOrAttachIso(_conn, cmd.getVmName(), isoPath, + * cmd.isAttach()); + */ + // setupSecStorage() + s_logger.debug(cmd.getStoreUrl() + " " + cmd.getIsoPath()); + return new Answer(cmd); + } catch (Exception e) { + s_logger.debug("Attach or detach ISO " + cmd.getIsoPath() + " for " + + cmd.getVmName() + " attach:" + cmd.isAttach() + " failed", + e); + return new Answer(cmd, false, e.getMessage()); + } + } + + @Override + public Answer attachIso(AttachCommand cmd) { + s_logger.debug("attachIso not implemented yet"); + return new Answer(cmd); + } + + @Override + public Answer dettachIso(DettachCommand cmd) { + s_logger.debug("detachIso not implemented yet"); + return new Answer(cmd); + } + + public String isoAttachDetach(String vmName, DiskTO disk, boolean isAttach) { + Xen xen = new Xen(c); + String doThis = (isAttach) ? "AttachIso" : "DettachIso"; + String msg = null; + try { + Xen.Vm vm = xen.getVmConfig(vmName); + /* check running */ + if (vm == null) { + msg = doThis + " can't find VM " + vmName; + return msg; + } + TemplateObjectTO isoTO = (TemplateObjectTO) disk.getData(); + DataStoreTO store = isoTO.getDataStore(); + if (!(store instanceof NfsTO)) { + msg = doThis + " unsupported protocol"; + return msg; + } + NfsTO nfsStore = (NfsTO) store; + String secPoolUuid = setupSecondaryStorage(nfsStore.getUrl()); + String isoPath = _ovmSec + File.separator + secPoolUuid + + File.separator + isoTO.getPath(); + s_logger.debug(doThis + " " + isoPath); + if (isAttach) { + /* check if iso is not already there ? */ + vm.addIso(isoPath); + } else { + if (!vm.removeDisk(isoPath)) { + msg = doThis + " failed for " + + vmName + " iso was not attached " + isoPath; + return msg; + } + } + xen.configureVm(_ovmObject.deDash(vm.getPrimaryPoolUuid()), + vm.getVmUuid()); + return msg; + } catch (Exception e) { + msg = doThis + " failed for " + vmName + " " + e.getMessage(); + return msg; + } finally { + if (msg == null) { + msg = "success"; + } + s_logger.debug(msg); + } + } + + public Answer execute(AttachCommand cmd) { + String vmName = cmd.getVmName(); + DiskTO disk = cmd.getDisk(); + Boolean success = false; + String answer = ""; + if (cmd.getDisk().getType() == Volume.Type.ISO) { + answer = isoAttachDetach(vmName, disk, true); + } + + if (answer == null) { + success = true; + } + return new Answer(cmd, success, answer); + } + + public Answer execute(DettachCommand cmd) { + String vmName = cmd.getVmName(); + DiskTO disk = cmd.getDisk(); + Boolean success = false; + String answer = ""; + if (cmd.getDisk().getType() == Volume.Type.ISO) { + answer = isoAttachDetach(vmName, disk, false); + } + + if (answer == null) { + success = true; + } + return new Answer(cmd, success, answer); + /* + * s_logger.debug("dettaching object: " + cmd.getDisk().getType()); + * if (this._vmstates.get(vmName) == State.Running) { + * return new DettachAnswer("Dettach unsupported on running VM " + * + vmName); + */ + } + + /* + * for now we assume that the datastore is there or else we + * never came this far + */ + public Answer execute(CreateObjectCommand cmd) { + // public Answer execute(CreateObjectCommand cmd) { + DataTO data = cmd.getData(); + s_logger.debug("creating new object: " + data.getObjectType()); + if (data.getObjectType() == DataObjectType.VOLUME) { + return createVolume(cmd); + } else if (data.getObjectType() == DataObjectType.SNAPSHOT) { + /* + * if stopped yes, if runniing ... no, unless we have ocfs2 + * when using raw partitions (file:) if using tap:aio we cloud... + */ + /* if (_vmstates(get)) { */ + } else if (data.getObjectType() == DataObjectType.TEMPLATE) { + /* aaalwaaays */ + } else { + + } + return new CreateObjectAnswer("Create unsupported object type: " + + data.getObjectType()); + } + + @Override + public Answer createVolume(CreateObjectCommand cmd) { + DataTO data = cmd.getData(); + VolumeObjectTO volume = (VolumeObjectTO) data; + try { + /* + * public Boolean storagePluginCreate(String uuid, String ssuuid, + * String + * host, String file, Integer size) + */ + String poolUuid = data.getDataStore().getUuid(); + String storeUrl = data.getDataStore().getUrl(); + URI uri = new URI(storeUrl); + String host = uri.getHost(); + String file = this._ovmRepo + "/" + _ovmObject.deDash(poolUuid) + + "/VirtualDisks/" + + volume.getUuid() + ".raw"; + Long size = volume.getSize(); + StoragePlugin sp = new StoragePlugin(c); + sp.storagePluginCreate(poolUuid, host, file, size); + sp.storagePluginGetFileInfo(file); + VolumeObjectTO newVol = new VolumeObjectTO(); + newVol.setName(volume.getName()); + newVol.setSize(sp.getFileSize()); + newVol.setPath(file); + return new CreateObjectAnswer(newVol); + } catch (Exception e) { + s_logger.debug("create volume failed: " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + } + + /* volumes are created on primary storage, ehm they should be ... */ + @Override + public Answer attachVolume(AttachCommand cmd) { + return new Answer(cmd); + } + + /* stub */ + @Override + public Answer dettachVolume(DettachCommand cmd) { + return new Answer(cmd); + } + + /* is it supported? */ + @Override + public Answer createSnapshot(CreateObjectCommand cmd) { + /* createsnap, but should be implemented */ + return new Answer(cmd); + } + + @Override + public Answer deleteVolume(DeleteCommand cmd) { + /* storagePluginDestroy(String ssuuid, String file) */ + DataTO data = cmd.getData(); + VolumeObjectTO volume = (VolumeObjectTO) data; + try { + String poolUuid = data.getDataStore().getUuid(); + /* needs the file attached too please... */ + String file = volume.getPath(); + if (file.endsWith("/")) { + file = volume.getPath() + "/" + volume.getUuid() + ".raw"; + } + StoragePlugin sp = new StoragePlugin(c); + sp.storagePluginDestroy(poolUuid, file); + s_logger.debug("delete volume success: " + file); + } catch (Exception e) { + s_logger.debug("delete volume failed: " + e.toString()); + return new CreateObjectAnswer(e.toString()); + } + return new Answer(cmd); + } + + /* copies it from secondary to primary ? */ + @Override + public Answer createVolumeFromSnapshot(CopyCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer deleteSnapshot(DeleteCommand cmd) { + /* storagePluginDestroy(String ssuuid, String file) */ + return new Answer(cmd); + } + + @Override + public Answer introduceObject(IntroduceObjectCmd cmd) { + return new Answer(cmd, false, "not implememented yet"); + } + + @Override + public Answer forgetObject(ForgetObjectCmd cmd) { + return new Answer(cmd, false, "not implememented yet"); + } + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/CloudStackPlugin.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/CloudStackPlugin.java new file mode 100644 index 0000000..94275f4 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/CloudStackPlugin.java
@@ -0,0 +1,131 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; +import java.util.HashMap; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +public class CloudStackPlugin extends OvmObject { + + public CloudStackPlugin(Connection c) { + client = c; + } + + public String getVncPort(String vmName) throws XmlRpcException { + String x = (String) callWrapper("get_vncport", vmName); + return x; + } + + public boolean ovsUploadSshKey(String key, String content) + throws XmlRpcException { + Object x = callWrapper("ovs_upload_ssh_key", key, content); + if (x==null) { + return false; + } + return true; + } + + public class ReturnCode { + private Map<String, Object> _rc = new HashMap<String, Object>() { + { + put("rc", null); + put("exit", null); + put("err", null); + put("out", null); + } + }; + public void setValues(Map<String, String> m) { + this._rc.putAll(m); + } + public Boolean getRc() { + try { + Long rc = (Long) _rc.get("rc"); + _rc.put("exit", rc); + if (rc != 0) + return false; + return true; + } catch (Exception e) { + + } + return false; + } + public String getStdOut() { + return (String) _rc.get("out"); + } + public String getStdErr() { + return (String) _rc.get("err"); + } + public Integer getExit() { + if (_rc.get("exit") == null) + _rc.put("exit", _rc.get("rc")); + return Integer.valueOf((String) _rc.get("exit")); + } + } + public ReturnCode domrExec(String ip, String cmd) throws XmlRpcException { + ReturnCode rc = new ReturnCode(); + rc.setValues((Map<String, String>) callWrapper("exec_domr", ip, cmd)); + return rc; + } + + public boolean domrCheckPort(String ip, Integer port, Integer retries, Integer interval) + throws XmlRpcException, InterruptedException { + Boolean x= false; + /* should deduct the interval from the timeout and sleep on it */ + Integer sleep=interval; + while(x == false && retries > 0) { + x = (Boolean) callWrapper("check_domr_port", ip, port, interval); + retries--; + Thread.sleep(sleep * 1000); + } + return x; + } + + public Map<String, String> ovsDom0Stats(String bridge) throws XmlRpcException { + Map<String, String> stats = (Map<String, String>) + callWrapper("ovs_dom0_stats", bridge); + return stats; + } + + + public Map<String, String> ovsDomUStats(String domain) throws XmlRpcException { + Map<String, String> stats = (Map<String, String>) + callWrapper("ovs_domU_stats", domain); + return stats; + } + public boolean domrCheckPort(String ip, Integer port) throws XmlRpcException { + Object x = callWrapper("check_domr_port", ip, port); + return (Boolean) x; + } + + public boolean domrCheckSsh(String ip) throws XmlRpcException { + Object x = callWrapper("check_domr_ssh", ip); + return (Boolean) x; + } + + public boolean ovsControlInterface(String dev, String ipmask) throws XmlRpcException { + Object x = callWrapper("ovs_control_interface", dev, ipmask); + return (Boolean) x; + } + + public boolean ping(String host) throws XmlRpcException { + Object x = callWrapper("ping", host); + return (Boolean) x; + } + + public boolean ovsCheckFile(String file) throws XmlRpcException { + Object x = callWrapper("ovs_check_file", file); + return (Boolean) x; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Cluster.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Cluster.java new file mode 100644 index 0000000..703f8a2 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Cluster.java
@@ -0,0 +1,162 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import org.apache.xmlrpc.XmlRpcException; + +/* + * should become an interface implementation + */ +public class Cluster extends OvmObject { + + public Cluster(Connection c) { + client = c; + } + + /* + * leave_cluster, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: + * self - default: None argument: poolfsUuid - default: None + */ + public Boolean leaveCluster(String poolfsUuid) throws XmlRpcException { + Object x = callWrapper("leave_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } + + /* + * configure_server_for_cluster, <class + * 'agent.api.cluster.o2cb.ClusterO2CB'> argument: self - default: None <( ? + * argument: o2cb_conf - default: None <( ? argument: clusterConf - + * default: None <( ? argument: poolfs_type - default: None argument: + * poolfs_target - default: None argument: poolfsUuid - default: None + * argument: poolfs_nfsbase_uuid - default: None + */ + public Boolean configureServerForCluster(String poolfsUuid) + throws XmlRpcException { + Object x = callWrapper("configure_server_for_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } + + /* + * deconfigure_server_for_cluster, <class + * 'agent.api.cluster.o2cb.ClusterO2CB'> argument: self - default: None + * argument: poolfsUuid - default: None + */ + public Boolean deconfigureServerForCluster(String poolfsUuid) + throws XmlRpcException { + Object x = callWrapper("deconfigure_server_for_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } + + /* + * join_cluster, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: self + * - default: None argument: poolfsUuid - default: None + */ + public Boolean joinCLuster(String poolfsUuid) throws XmlRpcException { + Object x = callWrapper("join_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } + + /* + * discover_cluster, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: + * self - default: None + */ + /* + * <Discover_Cluster_Result>< <O2CB_Config> + * <O2CB_HEARTBEAT_THRESHOLD>61</O2CB_HEARTBEAT_THRESHOLD> + * <O2CB_RECONNECT_DELAY_MS>2000</O2CB_RECONNECT_DELAY_MS> + * <O2CB_KEEPALIVE_DELAY_MS>2000</O2CB_KEEPALIVE_DELAY_MS> + * <O2CB_BOOTCLUSTER>ba9aaf00ae5e2d73</O2CB_BOOTCLUSTER> + * <O2CB_IDLE_TIMEOUT_MS>60000</O2CB_IDLE_TIMEOUT_MS> + * <O2CB_ENABLED>true</O2CB_ENABLED> <O2CB_STACK>o2cb</O2CB_STACK> + * </O2CB_Config> <Cluster_Information> <Stored> <Clusters> <Cluster> + * <Name>ba9aaf00ae5e2d73</Name> <Node_Count>1</Node_Count> + * <Heartbeat_Mode>global</Heartbeat_Mode> </Cluster> </Clusters> + * <Heartbeats> <Heartbeat> + * <Region>0004FB0000050000E70FBDDEB802208F</Region> + * <Cluster>ba9aaf00ae5e2d73</Cluster> </Heartbeat> </Heartbeats> <Nodes> + * <Node> <Number>0</Number> <IP_Port>7777</IP_Port> + * <IP_Address>192.168.1.64</IP_Address> <Name>ovm-1</Name> + * <Cluster_Name>ba9aaf00ae5e2d73</Cluster_Name> </Node> </Nodes> </Stored> + * </Cluster_Information> </Discover_Cluster_Result> + */ + /* returns xml - sigh */ + public Boolean discoverCluster() throws XmlRpcException { + Object x = callWrapper("discover_cluster"); + // System.out.println(x); + + return false; + } + + /* + * update_clusterConfiguration, <class + * 'agent.api.cluster.o2cb.ClusterO2CB'> argument: self - default: None + * argument: cluster_conf - default: None <( ? cluster_conf can be a "dict" + * or a plain file: print master.update_clusterConfiguration( + * "heartbeat:\n\tregion = 0004FB0000050000E70FBDDEB802208F\n\tcluster = ba9aaf00ae5e2d72\n\nnode:\n\tip_port = 7777\n\tip_address = 192.168.1.64\n\tnumber = 0\n\tname = ovm-1\n\tcluster = ba9aaf00ae5e2d72\n\nnode:\n\tip_port = 7777\n\tip_address = 192.168.1.65\n\tnumber = 1\n\tname = ovm-2\n\tcluster = ba9aaf00ae5e2d72\n\ncluster:\n\tnode_count = 2\n\theartbeat_mode = global\n\tname = ba9aaf00ae5e2d72\n" + * ) + */ + public Boolean updateClusterConfiguration(String clusterConf) + throws XmlRpcException { + Object x = callWrapper("update_clusterConfiguration", clusterConf); + if (x == null) + return true; + + return false; + } + + /* + * destroy_cluster, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: + * self - default: None argument: poolfsUuid - default: None + */ + public Boolean destroyCluster(String poolfsUuid) throws XmlRpcException { + Object x = callWrapper("destroy_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } + + /* + * is_cluster_online, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: + * self - default: None + */ + public Boolean isClusterOnline() throws XmlRpcException { + Object x = callWrapper("is_cluster_online"); + return Boolean.valueOf(x.toString()); + } + + /* + * create_cluster, <class 'agent.api.cluster.o2cb.ClusterO2CB'> argument: + * self - default: None argument: poolfsUuid - default: None + */ + public Boolean createCluster(String poolfsUuid) throws XmlRpcException { + Object x = callWrapper("create_cluster", poolfsUuid); + if (x == null) + return true; + + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Common.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Common.java new file mode 100644 index 0000000..ca24748 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Common.java
@@ -0,0 +1,64 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import org.apache.xmlrpc.XmlRpcException; + +/* + * should become an interface implementation + */ +public class Common extends OvmObject { + public String apiVersion; + + public Common(Connection c) { + client = c; + } + + /* + * get_api_version, <class 'agent.api.common.Common'> + */ + public String getApiVersion() throws XmlRpcException { + return callString("get_api_version"); + + } + + /* + * sleep, <class 'agent.api.common.Common'> argument: secs - default: None + */ + public String sleep(int seconds) throws XmlRpcException { + return callString("sleep", seconds); + } + + /* + * dispatch, <class 'agent.api.common.Common'> argument: uri - default: None + * argument: func - default: None + */ + /* + * normally used to push commands to other hosts in a cluster: * + * dispatch function join_server_pool + * to server https://oracle:******@192.168.1.67:8899/api/3/ + */ + public <T> String dispatch(String url, String function, T... args) + throws XmlRpcException { + return callString("dispatch", url, function, args); + } + + /* + * echo, <class 'agent.api.common.Common'> argument: msg - default: None + */ + public String echo(String msg) throws XmlRpcException { + return callString("echo", msg); + } + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Connection.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Connection.java new file mode 100644 index 0000000..53a8e10 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Connection.java
@@ -0,0 +1,144 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; +import java.net.URL; +import java.util.TimeZone; +import java.util.Vector; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.TimingOutCallback; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; + +public class Connection extends XmlRpcClient { + private static final Logger s_logger = Logger.getLogger(Connection.class); + private final XmlRpcClientConfigImpl _config = new XmlRpcClientConfigImpl(); + private XmlRpcClient _client; + private String _username; + private String _password; + private String _ip; + private Integer _port = 8898; + private Boolean _isSsl = false; + private String cert = ""; + private String key = ""; + private Integer timeout = 1200; /* seconds */ + private Integer _timeout = timeout * 1000; /* native is ms */ + + private XmlRpcClient getXmlClient() throws XmlRpcException { + // check ssl boolean + final XmlRpcClient client = new XmlRpcClient(); + + URL url; + try { + // here too + url = new URL("http://" + _ip + ":" + _port.toString()); + _config.setTimeZone(TimeZone.getTimeZone("UTC")); + _config.setServerURL(url); + _config.setReplyTimeout(0); // disable, we use asyncexecute to + // control timeout + _config.setConnectionTimeout(60000); + _config.setReplyTimeout(60 * 15000); + _config.setBasicUserName(_username); + _config.setBasicPassword(_password); + _config.setXmlRpcServer(null); + // _config.setEnabledForExtensions(true); + client.setConfig(_config); + client.setTypeFactory(new RpcTypeFactory(client)); + } catch (Throwable e) { + throw new XmlRpcException(e.getMessage()); + } + return client; + } + + public Connection(String ip, Integer port, String username, String password) + throws XmlRpcException { + _ip = ip; + _port = port; + _username = username; + _password = password; + _client = getXmlClient(); + } + + public Connection(String ip, String username, String password) + throws XmlRpcException { + _ip = ip; + _username = username; + _password = password; + _client = getXmlClient(); + } + + public Object call(String method, Vector<?> params) throws XmlRpcException { + /* default timeout is 10 mins */ + return callTimeoutInSec(method, params, this._timeout); + } + + public Object call(String method, Vector<?> params, boolean debug) + throws XmlRpcException { + /* default timeout is 10 mins */ + return callTimeoutInSec(method, params, this._timeout, debug); + } + + public Object callTimeoutInSec(String method, Vector<?> params, + int timeout, boolean debug) throws XmlRpcException { + TimingOutCallback callback = new TimingOutCallback(timeout * 1000); + if (debug) { + /* + * some parameters including user password should not be printed in + * log + */ + s_logger.debug("Call Ovm3 agent: " + method + " with " + params); + } + + long startTime = System.currentTimeMillis(); + _client.executeAsync(method, params, callback); + try { + return callback.waitForResponse(); + } catch (TimingOutCallback.TimeoutException to) { + throw to; + } catch (Throwable e) { + throw new XmlRpcException(-2, e.getMessage()); + } finally { + long endTime = System.currentTimeMillis(); + float during = (endTime - startTime) / 1000; // in secs + s_logger.debug("Ovm3 call " + method + " finished in " + during + + " secs, on " + _ip + ":" + _port); + } + } + + public Object callTimeoutInSec(String method, Vector<?> params, int timeout) + throws XmlRpcException { + return callTimeoutInSec(method, params, timeout, true); + } + + public String getIp() { + return _ip; + } + + public Integer getPort() { + return _port; + } + + public String getUserName() { + return _username; + } + + public String getPassword() { + return _password; + } + + public Boolean getIsSsl() { + return _isSsl; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Linux.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Linux.java new file mode 100644 index 0000000..3be9feb --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Linux.java
@@ -0,0 +1,612 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; + +/* + * should become an interface implementation + */ +public class Linux extends OvmObject { + private Integer _init = 0; + + /* + * use capabilities to match things later, perhaps also hardware discovery ? + * wrap getters and setters.... for Mapps... + */ + public Map<String, String> Capabilities = new HashMap<String, String>(); + /* + * MAX_CONCURRENT_MIGRATION_IN=1, ALL_VM_CPU_OVERSUBSCRIBE=True, + * HIGH_AVAILABILITY=True, LOCAL_STORAGE_ELEMENT=True, NFS=True, + * MTU_CONFIGURATION=True, CONCURRENT_MIGRATION=False, + * VM_MEMORY_ALIGNMENT=1048576, CLUSTERS=True, VM_SUSPEND=True, + * BOND_MODE_LINK_AGGREGATION=True, YUM_PACKAGE_MANAGEMENT=True, + * VM_VNC_CONSOLE=True, BOND_MODE_ACTIVE_BACKUP=True, + * MAX_CONCURRENT_MIGRATION_OUT=1, MIGRATION_SETUP=False, + * PER_VM_CPU_OVERSUBSCRIBE=True, POWER_ON_WOL=True, FIBRE_CHANNEL=True, + * ISCSI=True, HVM_MAX_VNICS=8} + */ + public Map<String, String> VMM = new HashMap<String, String>(); + public Map<String, String> VMMc = new HashMap<String, String>(); + public Map<String, String> NTP = new HashMap<String, String>(); + public Map<String, String> DateTime = new HashMap<String, String>(); + public Map<String, String> Generic = new HashMap<String, String>(); + /* + * {OS_Major_Version=5, Statistic=20, Membership_State=Unowned, + * OVM_Version=3.2.1-517, OS_Type=Linux, Hypervisor_Name=Xen, + * CPU_Type=x86_64, Manager_Core_API_Version=3.2.1.516, + * Is_Current_Master=false, OS_Name=Oracle VM Server, + * Server_Roles=xen,utility, Pool_Unique_Id=none, + * Host_Kernel_Release=2.6.39-300.22.2.el5uek, OS_Minor_Version=7, + * Agent_Version=3.2.1-183, Boot_Time=1392366638, RPM_Version=3.2.1-183, + * Exports=, Hypervisor_Type=xen, Host_Kernel_Version=#1 SMP Fri Jan 4 + * 12:40:29 PST 2013, + * Unique_Id=1d:d5:e8:91:d9:d0:ed:bd:81:c2:a6:9a:b3:d1:b7:ea, + * Manager_Unique_Id=none, Cluster_State=Offline, Hostname=ovm-1} + */ + public Map<String, String> hwVMM = new HashMap<String, String>(); + public Map<String, String> hwSystem = new HashMap<String, String>(); + public int localTime; + public int lastBootTime; + public String timeZone; + public String timeUTC; + public List<String> _mounts = null; + + // public Map<String, Map> Settings = new HashMap<String, Map>(); + + public Linux(Connection c) { + client = c; + } + + /* + * discover_server, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean discoverServer() throws Exception { + String cmd = "discover_server"; + Object result = callWrapper(cmd); + if (result == null) { + return false; + } + + Document xmlDocument = prepParse((String) result); + /* System.out.println(result); */ + /* could be more subtle */ + String path = "//Discover_Server_Result/Server"; + Capabilities = xmlToMap(path + "/Capabilities", xmlDocument); + VMM = xmlToMap(path + "/VMM/Version", xmlDocument); + VMMc = xmlToMap(path + "/VMM", xmlDocument); + NTP = xmlToMap(path + "/NTP", xmlDocument); + DateTime = xmlToMap(path + "/Date_Time", xmlDocument); + Generic = xmlToMap(path, xmlDocument); + + // System.out.println(Get("Agent_Version")); + + // System.out.println(Generic.toString()); + return true; + } + + public String getAgentVersion() throws ParserConfigurationException, IOException, Exception { + return this.Get("Agent_Version"); + } + public String getHostKernelRelease() throws ParserConfigurationException, IOException, Exception { + return this.Get("Host_Kernel_Release"); + } + public String getHostOs() throws ParserConfigurationException, IOException, + Exception { + return this.Get("OS_Name"); + } + public String getHostOsVersion() throws ParserConfigurationException, + IOException, Exception { + String ver = this.Get("OS_Major_Version") + "." + + this.Get("OS_Minor_Version"); + return ver; + } + public String getHypervisorName() throws ParserConfigurationException, IOException, Exception { + return this.Get("Hypervisor_Name"); + } + public String getHypervisorVersion() throws ParserConfigurationException, IOException, Exception { + String ver = this.getHypervisorMajor() + "." + + this.getHypervisorMinor() + "." + this.getHypervisorExtra(); + return ver; + } + public String getCapabilities() throws ParserConfigurationException, + IOException, Exception { + return this.Get("Capabilities"); + } + public String getHypervisorMajor() throws ParserConfigurationException, IOException, Exception { + return this.Get("Major"); + } + public String getHypervisorMinor() throws ParserConfigurationException, IOException, Exception { + return this.Get("Minor"); + } + public String getHypervisorExtra() throws ParserConfigurationException, + IOException, Exception { + return this.Get("Extra").replace(".", ""); + } + public String getManagerUuid() throws ParserConfigurationException, IOException, Exception { + return this.Get("Manager_Unique_Id"); + } + + public String getMembershipState() throws ParserConfigurationException, + IOException, Exception { + return this.Get("Membership_State"); + } + + public String getServerRoles() throws ParserConfigurationException, + IOException, Exception { + return this.Get("Server_Roles"); + } + public boolean getIsMaster() throws ParserConfigurationException, + IOException, Exception { + return Boolean.parseBoolean(this.Get("Is_Current_Master")); + } + public String getOvmVersion() throws ParserConfigurationException, IOException, Exception { + return this.Get("OVM_Version"); + } + public String getHostName() throws ParserConfigurationException, IOException, Exception { + return this.Get("Hostname"); + } + public Integer getCpuKhz() throws NumberFormatException, ParserConfigurationException, IOException, Exception { + return Integer.valueOf(this.Get("CPUKHz")); + } + public Integer getCpuSockets() throws NumberFormatException, ParserConfigurationException, IOException, Exception { + return Integer.valueOf(this.Get("SocketsPerNode")); + } + public Integer getCpuThreads() throws NumberFormatException, ParserConfigurationException, IOException, Exception { + return Integer.valueOf(this.Get("ThreadsPerCore")); + } + public Integer getCpuCores() throws NumberFormatException, ParserConfigurationException, IOException, Exception { + return Integer.valueOf(this.Get("CoresPerSocket")); + } + public Integer getTotalThreads() throws NumberFormatException, ParserConfigurationException, IOException, Exception { + return this.getCpuSockets() * this.getCpuCores() * this.getCpuThreads(); + } + + public Double getMemory() throws NumberFormatException, + ParserConfigurationException, IOException, Exception { + return Double.valueOf(this.Get("TotalPages")) * 4096; + } + + public Double getFreeMemory() throws NumberFormatException, + ParserConfigurationException, IOException, Exception { + return Double.valueOf(this.Get("FreePages")) * 4096; + } + public String getUuid() throws NumberFormatException, + ParserConfigurationException, IOException, Exception { + return this.Get("Unique_Id"); + } + + public String Get(String element) throws ParserConfigurationException, IOException, Exception { + if (this._init == 0) { + this.discoverHardware(); + this.discoverServer(); + this._init = 1; + } + if (Generic.containsKey(element)) + return Generic.get(element); + if (VMMc.containsKey(element)) + return VMMc.get(element); + if (VMM.containsKey(element)) + return VMM.get(element); + if (hwVMM.containsKey(element)) + return hwVMM.get(element); + if (hwSystem.containsKey(element)) + return hwSystem.get(element); + if (Capabilities.containsKey(element)) + return Capabilities.get(element); + return ""; + } + + /* + * unexport_fs, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: export_uuid - default: None + */ + + /* + * get_last_boot_time, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Integer getLastBootTime() throws XmlRpcException { + HashMap<String, Long> result = callMap("get_last_boot_time"); + if (result == null) + return null; + this.lastBootTime = result.get("last_boot_time").intValue(); + this.localTime = result.get("local_time").intValue(); + return lastBootTime; + } + + /* + * delete_yum_repo, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: repo_id - default: None + */ + + /* + * notify_manager, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: notification - default: None argument: data - + * default: None + */ + + /* + * update_core_api_bindings, <class 'agent.api.host.linux.Linux'> argument: + * self - default: None argument: url - default: None argument: option - + * default: None + */ + + /* + * set_datetime, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: year - default: None argument: month - default: + * None argument: day - default: None argument: hour - default: None + * argument: min - default: None argument: sec - default: None + */ + public Boolean setDateTime(int year, int month, int day, int hour, int min, + int sec) throws XmlRpcException { + Object x = callWrapper("set_datetime", year, month, day, hour, min, sec); + if (x == null) + return true; + + return false; + } + + /* + * list_package, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: name - default: None + */ + + /* + * discover_physical_luns, <class 'agent.api.host.linux.Linux'> argument: + * self - default: None argument: args - default: None + */ + public String discoverPhysicalLuns() throws XmlRpcException { + String x = (String) callWrapper("discover_physical_luns", ""); + return x; + } + + /* + * ovs_download_file, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: url - default: None argument: filename - default: + * None argument: option - default: None argument: obj - default: None + * argument: obj_current - default: None argument: obj_total - default: None + * argument: update_period - default: None + */ + + /* + * install_package, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: pkg_data - default: None argument: option - + * default: None + */ + + /* + * get_support_files, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + + /* + * export_fs, <class 'agent.api.host.linux.Linux'> argument: self - default: + * None argument: export_uuid - default: None argument: export_type - + * default: None argument: client - default: None argument: path - default: + * None argument: options - default: None + */ + + /* + * ovs_async_proc_status, <class 'agent.api.host.linux.Linux'> argument: + * self - default: None argument: pid - default: None + */ + + /* + * set_timezone, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: timezone - default: None argument: utc - default: + * None + */ + public Boolean setTimeZone(String tz, Boolean utc) throws XmlRpcException { + Object x = callWrapper("set_timezone", tz, utc); + if (x == null) + return true; + + return false; + } + + /* + * copy_file, <class 'agent.api.host.linux.Linux'> argument: self - default: + * None argument: src - default: None argument: dst - default: None + * argument: sparse - default: None argument: update_period - default: None + */ + public Boolean copyFile(String src, String dst) throws XmlRpcException { + Object x = callWrapper("copy_file", src, dst, false); + if (x == null) + return true; + + return false; + } + + public Boolean copyFile(String src, String dst, Boolean sparse) + throws XmlRpcException { + Object x = callWrapper("copy_file", src, dst, sparse); + if (x == null) + return true; + + return false; + } + + /* + * discover_mounted_file_systems, <class 'agent.api.host.linux.Linux'> + * argument: self - default: None argument: args - default: None + */ + /* + * <Discover_Mounted_File_Systems_Result> <Filesystem Type="nfs"> <Mount + * Dir="/nfsmnt/e080e318-91c2-47e5-a5ab-f3ab53790162"> + * <Device>cs-mgmt:/volumes/cs-data/secondary/</Device> + * <Mount_Options>rw,relatime + * ,vers=3,rsize=524288,wsize=524288,namlen=255,hard + * ,proto=tcp,port=65535,timeo + * =600,retrans=2,sec=sys,local_lock=none,addr=192.168.1.61</Mount_Options> + * </Mount> </Filesystem> ... </Discover_Mounted_File_Systems_Result> + */ + + public Boolean discoverMountedFs() throws XmlRpcException { + Object x = callWrapper("discover_mounted_file_systems"); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + /* Filesystem bits and bobs */ + private Map<String, FileSystem> fsList = null; + + public Map<String, FileSystem> getFileSystemList(String type) + throws ParserConfigurationException, IOException, Exception { + if (fsList == null) + this.discoverMountedFs(type); + + return fsList; + } + + public void setFileSystemList(Map<String, FileSystem> list) { + fsList = list; + } + public class FileSystem { + public Map<String, Object> _fs = new HashMap<String, Object>() { + { + put("Mount_Options", null); + put("Name", null); + put("Device", null); + put("Host", null); + put("Dir", null); + put("Mount_Point", null); + put("Uuid", null); + } + }; + + public String getUuid() { + return (String) _fs.get("Uuid"); + } + + public String setUuid(String uuid) { + return (String) _fs.put("Uuid", uuid); + } + public String getName() { + return (String) _fs.get("Name"); + } + + public String setName(String name) { + return (String) _fs.put("Name", name); + } + + public String getDevice() { + return (String) _fs.get("Device"); + } + + public String setDevice(String dev) { + return (String) _fs.put("Device", dev); + } + + public String getHost() { + if (getDevice() != null && getDevice().contains(":")) { + String spl[] = getDevice().split(":"); + setHost(spl[0]); + setMountPoint(spl[1]); + } else { + return null; + } + return (String) _fs.get("Host"); + } + + public String setHost(String host) { + return (String) _fs.put("Host", host); + } + + public String getDir() { + return (String) _fs.get("Dir"); + } + + public String setDir(String dir) { + return (String) _fs.put("Dir", dir); + } + + public String getMountPoint() { + if (getHost() != null) { + return (String) _fs.get("Mount_Point"); + } + return null; + } + public String setMountPoint(String pnt) { + return (String) _fs.put("Mount_Point", pnt); + } + }; + + /* should actually be called "getMountedsFsDevice" or something */ + public Map<String, FileSystem> discoverMountedFs(String type) + throws ParserConfigurationException, IOException, Exception { + // if (postDiscovery == null) { + // postDiscovery = callWrapper("discover_network"); + this.fsList = new HashMap<String, FileSystem>(); + //} + Object x = callWrapper("discover_mounted_file_systems", type); + Document xmlDocument = prepParse((String) x); + // List<String> list = new ArrayList<String>(); + String bpath = "//Discover_Mounted_File_Systems_Result/Filesystem"; + String mpath = bpath + "/Mount/@Dir"; + _mounts = xmlToList(mpath, xmlDocument); + for (String mnt : _mounts) { + String dpath = bpath + "/Mount[@Dir='" + mnt + "']"; + Map<String, Object> fs = xmlToMap(dpath, xmlDocument); + FileSystem f = new FileSystem(); + f._fs = fs; + String[] spl = mnt.split("/"); + String uuid = spl[spl.length - 1]; + // System.out.println(uuid + " " + mnt); + f.setUuid(uuid); + f.setDir(mnt); + fsList.put(uuid, f); + } + setFileSystemList(fsList); + if (x == null) { + return this.fsList; + } + + return this.fsList; + } + + /* + * ovs_async_proc, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: func - default: None + */ + + /* + * get_log, <class 'agent.api.host.linux.Linux'> argument: self - default: + * None argument: loglist - default: None + */ + + /* + * update_agent_password, <class 'agent.api.host.linux.Linux'> argument: + * self - default: None argument: username - default: None argument: + * password - default: None + */ + public Boolean updateAgentPassword(String user, String pass) + throws XmlRpcException { + Object x = callWrapper("update_agent_password", user, pass); + if (x == null) + return true; + + return false; + } + + /* + * yum_update, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: option - default: None + */ + + /* + * discover_hardware, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean discoverHardware() + throws ParserConfigurationException, IOException, Exception { + Object result = callWrapper("discover_hardware"); + + Document xmlDocument = prepParse((String) result); + /* could be more subtle */ + String path = "//Discover_Hardware_Result/NodeInformation"; + hwVMM = xmlToMap(path + "/VMM/PhysicalInfo", xmlDocument); + hwSystem = xmlToMap(path + "/DMTF/System", xmlDocument); + + if (result == null) + return true; + + return false; + } + + /* + * uninstall_package, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: pkg_list - default: None argument: option - + * default: None + */ + + /* + * get_datetime, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Integer getDateTime() throws XmlRpcException { + this.getLastBootTime(); + return this.localTime; + } + + /* + * configure_yum, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: section - default: None argument: params - + * default: None + */ + + /* + * get_yum_config, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean getYumConfig() throws XmlRpcException { + Object x = callWrapper("get_yum_config"); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + /* + * ovs_async_proc_stop, <class 'agent.api.host.linux.Linux'> argument: self + * - default: None argument: pid - default: None + */ + + /* + * set_statistic_interval, <class 'agent.api.host.linux.Linux'> argument: + * interval - default: None + */ + public Boolean setStatisticsInterval(int val) throws XmlRpcException { + Object x = callWrapper("set_statistics_interval", val); + if (x == null) + return true; + + return false; + } + + /* + * yum_list_package, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None argument: pkgnarrow - default: None argument: patterns - + * default: None argument: showdups - default: None argument: ignore_case - + * default: None + */ + + /* + * get_timezone, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean getTimeZone() throws XmlRpcException { + Object[] result = (Object[]) callWrapper("get_timezone"); + if (result != null) { + this.timeZone = result[0].toString(); + this.timeUTC = result[1].toString(); + return true; + } + return false; + } + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Network.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Network.java new file mode 100644 index 0000000..0ae9d84 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Network.java
@@ -0,0 +1,628 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +// import java.util.Map; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; +// import java.util.HashMap; + +/* + * should become an interface implementation + */ +public class Network extends OvmObject { + + public Network(Connection c) { + client = c; + } + + private Map<String, Interface> interfaceList = null; + + public Map<String, Interface> getInterfaceList() + throws ParserConfigurationException, IOException, Exception { + try { + this.discoverNetwork(); + } catch (Exception e) { + throw new Exception(e.getMessage()); + } + return interfaceList; + } + + public void setBridgeList(Map<String, Interface> list) { + interfaceList = list; + } + + public class Interface { + private Map<String, String> _interface = new HashMap<String, String>() { + { + put("Type", null); + put("Physical", null); + put("Name", null); + put("Address", null); + put("Broadcast", null); + put("MAC", null); + put("Vlan", null); + } + }; + + public void setIfType(String t) { + this._interface.put("Type", t); + } + public String getIfType() { + return this._interface.get("Type"); + } + public void setInterface(Map<String, String> itf) { + this._interface.putAll(itf); + } + + public String getName() { + return _interface.get("Name"); + } + + public String getPhysical() { + return _interface.get("Physical"); + } + + public String getAddress() { + return _interface.get("Address"); + } + + public String getBroadcast() { + return _interface.get("Broadcast"); + } + + public String getMac() { + return _interface.get("MAC"); + } + + public String setName(String name) { + return _interface.put("Name", name); + } + + public String setPhysical(String ph) { + return _interface.put("Physical", ph); + } + public String setAddress(String addr) { + return _interface.put("Address", addr); + } + + public String setBroadcast(String bcast) { + return _interface.put("Broadcast", bcast); + } + + public String setMac(String mac) { + return _interface.put("MAC", mac); + } + } + + private Network.Interface _getInterface(String key, String val) + throws ParserConfigurationException, IOException, Exception { + HashMap<String, Network.Interface> ifaces = new HashMap<String, Network.Interface>(); + ifaces = (HashMap<String, Interface>) this.getInterfaceList(); + for (final Entry<String, Interface> iface : ifaces.entrySet()) { + String match = "default"; + if (key.equals("Address")) + match = iface.getValue().getAddress(); + if (key.equals("Name")) + match = iface.getKey(); + // .getName(); + if (match != null && match.equals(val)) + return iface.getValue(); + } + return null; + } + + public Network.Interface getInterfaceByIp(String ip) + throws ParserConfigurationException, IOException, Exception { + return _getInterface("Address", ip); + } + + public Network.Interface getInterfaceByName(String name) + throws ParserConfigurationException, IOException, Exception { + return _getInterface("Name", name); + } + /* check if it is a BRIDGE */ + public String getPhysicalByBridgeName(String name) + throws ParserConfigurationException, IOException, Exception { + return getInterfaceByName(name).getPhysical(); + } + + public Network.Interface getBridgeByName(String name) + throws ParserConfigurationException, IOException, Exception { + if (_getInterface("Name", name).getIfType().contentEquals("Bridge")) { + return _getInterface("Name", name); + } + return null; + } + public Network.Interface getBridgeByIp(String ip) + throws ParserConfigurationException, IOException, Exception { + if (_getInterface("Address", ip).getIfType().contentEquals("Bridge")) { + return _getInterface("Address", ip); + } + return null; + } + private Object postDiscovery = null; + + private List<String> netInterfaces = new ArrayList<String>(); + + /* + * ovs_bond_mode, <class 'agent.api.network.linux_network.LinuxNetwork'> + Change Bond mode. + + @param bond One of the logical channel bonds (bond0, bond1 ...etc) + @mode Current supported bonding modes (1 = active-backup, 4 = 802.3ad + 6 = balance-alb). + @return If successful, returns bond's names and its new mode + Raises an exception on failure + Restriction: + -bond must be one of the logical channel bonds (bond0, bond1 ...etc) + + */ + public Boolean ovsBondMode(String bond, String mode) throws XmlRpcException { + Object x = callWrapper("ovs_bond_mode", bond, mode); + if (x == null) + return true; + + return false; + } + + /* + * ovs_change_mtu, <class 'agent.api.network.linux_network.LinuxNetwork'> + Changes MTU on a physical,vlan,bond,and bridge interface. + Changing a bond MTU will also change the MTU of its slaves. + Changing the MTU of an interface that is part of a bridge, + will cause the bridge MTU and all of the interfaces change. + When a Guest VIF attach to a bridge,the VIF MTU will be set + to the bridge MTU + + + @param interface Physical,bond,vlan, and a bridge + @param MTU Values are 1500 to 64000 + + @return If successful, returns the interface, and the new MTU + Raises an exception on failure + + Restriction: + -Can not change the MTU of a bridge without interfaces. + -VLAN MTU must less or equal to the MTU of the underlying + physical interface. + */ + public Boolean ovsChangeMtu(String net, int mtu) throws XmlRpcException { + Object x = callWrapper("ovs_change_mtu", net, mtu); + if (x == null) + return true; + + return false; + } + + /* + * ovs_async_bridge, <class 'agent.api.network.linux_network.LinuxNetwork'> + * argument: self - default: None argument: action - default: None argument: + * br_name - default: None argument: net_dev - default: None + */ + public Boolean ovsAsyncBridge(String action, String bridge, String netdev) + throws XmlRpcException { + Object x = callWrapper("ovs_async_bridge", action, bridge, netdev); + if (x == null) + return true; + + return false; + } + + /* + * ovs_bond_op, <class 'agent.api.network.linux_network.LinuxNetwork'> + * argument: self - default: None argument: action - default: None argument: + * bond - default: None argument: backup - default: None + */ + public Boolean ovsBondOp(String action, String bond, String backup) + throws XmlRpcException { + Object x = callWrapper("ovs_bond_op", action, bond, backup); + if (x == null) + return true; + + return false; + } + + /* + * configure_virtual_ip, <class + * 'agent.api.network.linux_network.LinuxNetwork'> argument: self - default: + * None argument: virtual_ip - default: None argument: base_ip - default: + * None + */ + public Boolean configureVip(String vip, String baseip) + throws XmlRpcException { + Object x = callWrapper("configure_virtual_ip", vip, baseip); + if (x == null) + return true; + + return false; + } + + /* + * ovs_ip_config, <class 'agent.api.network.linux_network.LinuxNetwork'> + Assigns/flushes IP, netmask address to a physical,VLAN, and bond interfaces. + + @param interface The interface on which to assign + @param optype (static|dynamic|flush) + static: Assigns the given IP, and netmask to the interface, and + saves the config file to /etc/sysconfig/network-scripts. + dynamic: Flushes current address, and creats and save the config + file to /etc/sysconfig/network-scripts, (BOOTPROTO=dhcp) + flush: flushes the interface address,routes, removes the current + config file from /etc/sysconfig/network-scripts. + Creats a new one with BOOTPROTO=static + + @args Required for the static option, otherwise it is ignored + IP address: IPv4 address in decimal notation (101.230.112) + netmask: Standard netmask in a decimal notation,NOT CIDR. + example(255.255.255.0) + + @return If successful, returns the interface, and addresses added/flushed + Raises an exception on failure + + Restriction: + -Interface must be physical, VLAN, or a Bond + -Interface must not be a bridge port, or slave to a bond + -Addresses must be valid in a decimal notation + + */ + public Boolean ovsIpConfig(String net, String optype, String ip, + String netmask) + throws XmlRpcException { + Object x = callWrapper("ovs_ip_config", net, optype, ip, netmask); + if (x == null) + return true; + + return false; + } + + /* + * ovs_if_meta, <class 'agent.api.network.linux_network.LinuxNetwork'> + This function creates meta data file meta-interface, and write the string + (METADATA=data) to it. This string is used by the manager to identify + networks that interfaces belong to. Dom0 does not make used of this string, + it just saves it and returns it during running, saved network discovery. + + - If an interface already has a meta data string, then it gets + replace by the new one + - An empty meta data string, indicates to remove the existing string + (remove the meta-interface) file + + @param interface physical,VLAN, bond ...etc interfaces + @param data meta data to save + + @return If successful, returns the interface, and meta data + Raises an exception on failure + + Restriction: + - data string that starts with leading spaces will be rejected + * ovs_if_meta('bond0', + * 'ethernet:c0a80100{192.168.1.0}:MANAGEMENT,CLUSTER_HEARTBEAT,LIVE_MIGRATE,VIRTUAL_MACHINE,STORAGE') + */ + public Boolean ovsIfMeta(String net, String data) throws XmlRpcException { + Object x = callWrapper("ovs_if_meta", net, data); + if (x == null) + return true; + + return false; + } + + + /* + * ovs_bond_config, <class 'agent.api.network.linux_network.LinuxNetwork'> + * argument: self - default: None argument: action - default: None argument: + * bond - default: None + */ + public Boolean ovsBondConfig(String action, String bond) + throws XmlRpcException { + Object x = callWrapper("ovs_bond_config", action, bond); + if (x == null) + return true; + + return false; + } + + /* + * discover_network, <class 'agent.api.network.linux_network.LinuxNetwork'> + Discover information about the current network configuration. + This includes the state of physical NICs, bonds, and bridges. Also return + information stored for this server that is needed to configure + the network when the OVM Manager is not available. + + Discovery of the current network configuration is handled by invoking + a python extension that calls legacy C code from the VI agent. + + @param None + + @return Returns the discovery data as an XML document. + Raises an exception on failure. + * <?xml version="1.0" ?> <Discover_Network_Result> + * <Network><Active><Network> <Device Name="eth0"> + * <MAC>52:54:00:24:47:70</MAC> <Flags>(0x1843) IFF_UP IFF_BROADCAST + * IFF_RUNNING IFF_SLAVE IFF_MULTICAST</Flags> <ETHTOOL> <Autonegotiate> + * <State>Complete</State> <Speed>1000baseT-FD</Speed> </Autonegotiate> + * <Link>ok</Link> <Capabilities>10baseT-HD 10baseT-FD 100baseT-HD + * 100baseT-FD 1000baseT-FD</Capabilities> <Advertising>10baseT-HD + * 10baseT-FD 100baseT-HD 100baseT-FD 1000baseT-FD</Advertising> </ETHTOOL> + * <WOL> <WakeOnLan>disabled</WakeOnLan> </WOL> <SysFS> + * <uevent>INTERFACE=eth0 IFINDEX=2</uevent> + * <addr_assign_type>0</addr_assign_type> <addr_len>6</addr_len> + * <dev_id>0x0</dev_id> <ifalias/> <iflink>2</iflink> <ifindex>2</ifindex> + * <features>0x40014ba9</features> <type>1</type> <link_mode>0</link_mode> + * <carrier>1</carrier> <speed>1000</speed> <duplex>full</duplex> + * <dormant>0</dormant> <operstate>up</operstate> <mtu>1500</mtu> + * <flags>0x1903</flags> <tx_queue_len>1000</tx_queue_len> + * <netdev_group>0</netdev_group> <SysFSDev> <vendor>0x8086</vendor> + * <device>0x100e</device> <subsystem_vendor>0x1af4</subsystem_vendor> + * <subsystem_device>0x1100</subsystem_device> <class>0x020000</class> + * </SysFSDev> </SysFS> <BootProto>none</BootProto> </Device> .... + * </Network> <Bonding> <Device Name="bond0"> + * <Bonding_Mode>active-backup</Bonding_Mode> <Primary_Slave>eth0 + * (primary_reselect always)</Primary_Slave> + * <Currently_Active_Slave>eth0</Currently_Active_Slave> + * <MII_Status>up</MII_Status> + * <MII_Polling_Interval>250</MII_Polling_Interval> <Up_Delay>500</Up_Delay> + * <Down_Delay>500</Down_Delay> <Slave_Interface Name="eth0"> + * <MII_Status>up</MII_Status> <Speed>1000 Mbps</Speed> + * <Duplex>full</Duplex> <Link_Failure_Count>0</Link_Failure_Count> + * <Permanent_HW_addr>52:54:00:24:47:70</Permanent_HW_addr> + * </Slave_Interface> <Family Type="AF_INET"> <MAC>52:54:00:24:47:70</MAC> + * <mtu>1500</mtu> </Family> <BootProto>none</BootProto> + * <MetaData>ethernet:c0a80100 + * {192.168.1.0}:MANAGEMENT,CLUSTER_HEARTBEAT,LIVE_MIGRATE + * ,VIRTUAL_MACHINE,STORAGE</MetaData> </Device> </Bonding> <Bridges> + * <Device Name="c0a80100"> <Family Type="AF_INET"> + * <MAC>52:54:00:24:47:70</MAC> <Address>192.168.1.64</Address> + * <Netmask>255.255.255.0</Netmask> <Broadcast>192.168.1.255</Broadcast> + * </Family> <Interfaces> <PhyInterface>bond0</PhyInterface> </Interfaces> + * <BootProto>static</BootProto></Device> </Bridges> <Infiniband> + * </Infiniband> </Active></Network></Discover_Network_Result> + */ + /* put more in when required, for now ok */ + public Boolean discoverNetwork() throws ParserConfigurationException, + IOException, Exception { + // if (postDiscovery == null) { + postDiscovery = callWrapper("discover_network"); + this.interfaceList = new HashMap<String, Interface>(); + // } + // System.out.println(postDiscovery); + Document xmlDocument = prepParse((String) postDiscovery); + String path = "//Discover_Network_Result/Network/Active"; + String bpath = path + "/Bridges/Device"; + + netInterfaces = new ArrayList<String>(); + netInterfaces.addAll(xmlToList(bpath + "/@Name", + xmlDocument)); + for (String b : netInterfaces) { + Map<String, String> br = xmlToMap(bpath + "[@Name='" + b + + "']/Family", xmlDocument); + /* vifs are here too */ + String phyInt = (String) this.xmlToMap(bpath + "[@Name='" + b + + "']/Interfaces", xmlDocument).get("PhyInterface"); + Interface iface = new Interface(); + iface.setInterface(br); + iface.setName(b); + iface.setIfType("Bridge"); + if (phyInt == null) { + iface.setIfType("Local"); + } + iface.setPhysical(phyInt); + interfaceList.put(b, iface); + } + /* add "physical" interfaces */ + bpath = path + "/Network/Device"; + netInterfaces = new ArrayList<String>(); + netInterfaces.addAll(xmlToList(bpath + "/@Name", xmlDocument)); + for (String p : netInterfaces) { + Map<String, String> nf = xmlToMap("//Device[@Name='" + p + + "']", xmlDocument); + Interface iface = new Interface(); + iface.setPhysical(nf.get("Basename")); + iface.setName(p); + iface.setMac(nf.get("MAC")); + iface.setIfType("Physical"); + interfaceList.put(p, iface); + } + /* add virtual interfaces ? */ + if (postDiscovery == null) + return false; + + return true; + } + + /* + * ovs_local_config, <class 'agent.api.network.linux_network.LinuxNetwork'> + Configure a Local Bridge ((NIC-less bridge) + + @param action (start | stop) + start: Creates local bridge without a physical interface, and saves bridge config + file in /etc/sysconfig/network-scripts + stop: Deletes local bridge, removes bridge config file from + /etc/sysconfig/network-scripts + + @param br_name The bridge name to add + + @return If successful, returns the name of the bridge + Raises an exception on failure + + */ + public Boolean startOvsLocalConfig(String br) + throws XmlRpcException { + return ovsLocalConfig("start", br); + } + + public Boolean stopOvsLocalConfig(String br) + throws XmlRpcException { + return ovsLocalConfig("stop", br); + } + + public Boolean ovsLocalConfig(String action, String br) + throws XmlRpcException { + Object x = callWrapper("ovs_local_config", action, br); + if (x == null) + return true; + + return false; + } + + /* + * ovs_vlan_config, <class 'agent.api.network.linux_network.LinuxNetwork'> + Creates a VLAN interface on a physical, or a bond interface. + + @param action (add|remove) + add: Creates a VLAN on an interface,saves the VLAN config file in + /etc/sysconfig/network-scripts + remove: Removes a VLAN from an interfacei,removes its config file from + /etc/sysconfig/network-scripts + + @param interface The interface on which to create a VLAN + @param vlanid VLAN ID (2-4095) + + @return If successful, returns the interface, and VLAN created + Raises an exception on failure + + Restriction: + -Interface must be physical, or bond + -Interface must not be member of a bridge, or slave to a bond + -VLAN ID must not exist on the same interface + + */ + public Boolean startOvsVlanConfig(String dev, int vlan) + throws XmlRpcException { + return ovsVlanConfig("add", dev, vlan); + } + + public Boolean stopOvsVlanConfig(String dev, int vlan) + throws XmlRpcException { + return ovsVlanConfig("del", dev, vlan); + } + public Boolean ovsVlanConfig(String action, String net, int vlan) + throws XmlRpcException { + Object x = callWrapper("ovs_vlan_config", action, net, vlan); + if (x == null) + return true; + + return false; + } + + /* + * ovs_br_config, <class 'agent.api.network.linux_network.LinuxNetwork'> + Configure a Standard Bridge. + + @param action (start | stop) + start: Creates the bridge, Copies the IP and MAC addresses from netdev to bridge, + enslaves net_dev to bridge, and saves bridge config files in + /etc/sysconfig/network-scripts + stop: Removes net_dev from the bridge,transfers addresses, routes from bridge to + net_dev, deletes the bridge, and revomes bridge config files from + /etc/sysconfig/network-scripts + + @param br_name The bridge name to add + @param net_dev The physical interface to add to the bridge + + @return If successful, returns the names of the bridge and it's physical interface. + Raises an exception on failure + Restriction: + -net_dev must be physical, or bond + -net_dev must not be member of a bridge, or slave to a bond + */ + public Boolean startOvsBrConfig(String br, String dev) + throws XmlRpcException { + return ovsBrConfig("start", br, dev); + } + + public Boolean stopOvsBrConfig(String br, String dev) + throws XmlRpcException { + return ovsBrConfig("stop", br, dev); + } + + public Boolean ovsBrConfig(String action, String br, String net) + throws XmlRpcException { + Object x = callWrapper("ovs_br_config", action, br, net); + if (x == null) + return true; + + return false; + } + + /* + * ovs_vlan_bridge, <class 'agent.api.network.linux_network.LinuxNetwork'> + @param action (start | stop) + start: Creates the bridge, creats VLAN on net_dev,enslaves + the VLAN to the bridge, and saves VLAN bridge config + files in /etc/sysconfig/network-scripts + stop: Removes the VLAN from the bridge, removes the VLAN, + deletes the bridge, and removes VLAN bridge config files + from /etc/sysconfig/network-scripts + + @param br_name The bridge name to add + @param net_dev The physical interface on which to create a VLAN. + @param vlan_id VLAN ID (1-4095). VLAN ID of 1 is the untagged VLAN. + + @return If successful, returns the names of the bridge and it's VLAN interface + Raises an exception on failure + */ + public Boolean stopOvsVlanBridge(String br, String net, int vlan) throws XmlRpcException { + return ovsVlanBridge("stop", br, net, vlan); + } + + public Boolean startOvsVlanBridge(String br, String net, int vlan) throws XmlRpcException { + return ovsVlanBridge("start", br, net, vlan); + } + + public Boolean ovsVlanBridge(String action, String br, String net, int vlan) + throws XmlRpcException { + Object x = callWrapper("ovs_vlan_bridge", action, br, net, vlan); + if (x == null) + return true; + + return false; + } + + /* + * deconfigure_virtual_ip, <class + * 'agent.api.network.linux_network.LinuxNetwork'> argument: self - default: + * None argument: virtual_ip - default: None + */ + public Boolean deconfigureVip(String vip) throws XmlRpcException { + Object x = callWrapper("deconfigure_virtual_ip", vip); + if (x == null) + return true; + + return false; + } + + /* + * ovs_async_bond, <class 'agent.api.network.linux_network.LinuxNetwork'> + * argument: self - default: None argument: action - default: None argument: + * bond - default: None + */ + public Boolean ovsAsyncBond(String action, String bond) + throws XmlRpcException { + Object x = callWrapper("ovs_async_bond", action, bond); + if (x == null) + return true; + + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Ntp.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Ntp.java new file mode 100644 index 0000000..96b1b4e --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Ntp.java
@@ -0,0 +1,140 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.xmlrpc.XmlRpcException; + +/* + * should become an interface implementation + */ +public class Ntp extends OvmObject { + private List<String> Servers = new ArrayList<String>(); + private Boolean isServer = null; + private Boolean isRunning = null; + + public Ntp(Connection c) { + client = c; + } + + public List<String> addServer(String server) { + if (Servers.contains(server) == false) + Servers.add(server); + + return Servers; + } + + public List<String> removeServer(String server) { + if (Servers.contains(server)) + Servers.remove(server); + + return Servers; + } + + public List<String> servers() { + return Servers; + } + + public Boolean isRunning() { + return isRunning; + } + + public Boolean isServer() { + return isServer; + } + + public Boolean getDetails() throws XmlRpcException { + return this.getNtp(); + } + + /* + * get_ntp, <class 'agent.api.host.linux.Linux'> argument: self - default: + * None + */ + public Boolean getNtp() throws XmlRpcException { + Object[] v = (Object[]) callWrapper("get_ntp"); + int c = 0; + for (Object o : v) { + // System.out.println(o.getClass()); + if (o instanceof java.lang.Boolean) { + if (c == 0) + this.isServer = (Boolean) o; + + if (c == 1) + this.isRunning = (Boolean) o; + + // should not get here + if (c > 1) + return false; + + c += 1; + } else if (o instanceof java.lang.Object) { + Object[] S = (Object[]) o; + for (Object m : S) { + this.addServer((String) m); + } + } + } + return true; + } + + /* + * set_ntp, <class 'agent.api.host.linux.Linux'> argument: self - default: + * None argument: servers - default: None argument: local_time_source - + * default: None argument: allow_query - default: None // right, can't be + * set eh + */ + public Boolean setNtp(List<String> servers, Boolean running) + throws XmlRpcException { + if (callWrapper("set_ntp", servers, running) == null) { + return this.getNtp(); + } else { + return false; + } + } + + /* also cleans the vector */ + public Boolean setNtp(String server, Boolean running) + throws XmlRpcException { + this.Servers = new ArrayList<String>(); + this.Servers.add(server); + return setNtp(this.Servers, running); + } + + public Boolean setNtp(Boolean running) throws XmlRpcException { + return setNtp(this.Servers, running); + } + + /* + * disable_ntp, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean disableNtp() throws XmlRpcException { + if (callWrapper("disable_ntp") == null) + return true; + return false; + } + + /* + * enable_ntp, <class 'agent.api.host.linux.Linux'> argument: self - + * default: None + */ + public Boolean enableNtp() throws XmlRpcException { + if (callWrapper("enable_ntp") == null) + return true; + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/OvmObject.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/OvmObject.java new file mode 100644 index 0000000..4dba83c --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/OvmObject.java
@@ -0,0 +1,208 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class OvmObject { + public static Connection client = null; + public static Vector<?> emptyParams = new Vector<Object>(); + + /* remove dashes from uuids */ + public String deDash(String str) { + final String x = str.replaceAll("-", ""); + return x; + } + + /* generate a uuid */ + public String newUuid() { + final String uuid = UUID.randomUUID().toString(); + return uuid; + } + + /* generate a uuid */ + public String newUuid(String str) { + final String uuid = UUID.nameUUIDFromBytes(str.getBytes()).toString(); + return uuid; + } + + /* capture most of the calls here */ + public static Object callWrapper(String call) throws XmlRpcException { + try { + Object res = client.call(call, emptyParams); + return res; + } catch (XmlRpcException e) { + throw new XmlRpcException(e.getMessage()); + } + } + + /* nice try but doesn't work like that .. */ + @SafeVarargs + public static <T> Object callWrapper(String call, T... args) + throws XmlRpcException { + Vector<T> params = new Vector<T>(); + for (T param : args) { + params.add(param); + } + // return + Object res = client.call(call, params); + return res; + } + + /* returns a single string */ + public HashMap<String, Long> callMap(String call) throws XmlRpcException { + HashMap<String, Long> result = (HashMap<String, Long>) callWrapper(call); + return result; + } + + public <T> String callString(String call, T... args) throws XmlRpcException { + Object result = callWrapper(call, args); + if (result == null) { + return null; + } + if (result instanceof String) + return result.toString(); + if (result instanceof Integer) + return result.toString(); + if (result instanceof Long) + return result.toString(); + if (result instanceof HashMap) + return result.toString(); + + Object[] results = (Object[]) result; + + if (results.length == 0) + // return results[0].toString(); + return null; + + if (results.length == 1) + return results[0].toString(); + + return null; + } + + /* was String, Object before */ + public <E> Map<String, E> xmlToMap(String path, Document xmlDocument) + throws XPathExpressionException { + XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + // capabilities, date_time etc + XPathExpression xPathExpression = xPath.compile(path); + NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDocument, + XPathConstants.NODESET); + + Map<String, E> myMap = new HashMap<String, E>(); + for (int ind = 0; ind < nodeList.getLength(); ind++) { + NodeList nodeListFor = nodeList.item(ind).getChildNodes(); + for (int index = 0; index < nodeListFor.getLength(); index++) { + String rnode = nodeListFor.item(index).getNodeName(); + NodeList nodeListFor2 = nodeListFor.item(index).getChildNodes(); + if (nodeListFor2.getLength() > 1) { + // System.out.println("multiball"); + /* + * for (int i = 0; i < nodeListFor2.getLength(); i++) { + * String node = nodeListFor2.item(i).getNodeName(); String + * element = nodeListFor2.item(i).getTextContent(); + * System.out.println("rnode: " + rnode + " -> node " + node + * + " ---> " + element); myMap.put(node, element); } + */ + } else { + String element = nodeListFor.item(index).getTextContent(); + // System.out.println("rnode " + rnode + " ---> " + + // element); + myMap.put(rnode, (E) element); + } + } + } + return myMap; + } + + public List<String> xmlToList(String path, Document xmlDocument) + throws XPathExpressionException { + List<String> list = new ArrayList<String>(); + XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + + XPathExpression xPathExpression = xPath.compile(path); + NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDocument, + XPathConstants.NODESET); + + for (int ind = 0; ind < nodeList.getLength(); ind++) { + // System.out.println(nodeList.item(ind).getTextContent()); + if (!nodeList.item(ind).getTextContent().isEmpty()) { + list.add("" + nodeList.item(ind).getTextContent()); + } else { + list.add("" + nodeList.item(ind).getNodeValue()); + } + } + return list; + } + + public String xmlToString(String path, Document xmlDocument) + throws XPathExpressionException { + + XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance(); + XPath xPath = factory.newXPath(); + + XPathExpression xPathExpression = xPath.compile(path); + NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDocument, + XPathConstants.NODESET); + // put a try in here too, so we can get the subbies + String x = nodeList.item(0).getTextContent(); + return x; + } + + public Document prepParse(String input) + throws ParserConfigurationException, Exception, IOException { + DocumentBuilderFactory builderfactory = DocumentBuilderFactory + .newInstance(); + builderfactory.setNamespaceAware(true); + + DocumentBuilder builder = builderfactory.newDocumentBuilder(); + Document xmlDocument = builder.parse(new InputSource(new StringReader( + (String) input))); + return xmlDocument; + } + /* + * returns a list of strings public <T> ArrayList<String> call(String call, + * T... args) throws XmlRpcException { ArrayList<String> data = new + * ArrayList<String>(); Object[] result = (Object[]) callWrapper(call, + * args); + * + * if (result[result.length] != null) return null; + * + * for(Object x : result) { data.add(x.toString()); } return data; } + */ +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Pool.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Pool.java new file mode 100644 index 0000000..2b87c70 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Pool.java
@@ -0,0 +1,362 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.apache.commons.lang.StringUtils; +import org.apache.xmlrpc.XmlRpcException; + +/* + * synonym to the pool python lib in the ovs-agent + */ +public class Pool extends OvmObject { + /* + * {Pool_Filesystem_Target=cs-mgmt:/volumes/cs-data/secondary, + * Pool_Filesystem_Type=nfs, + * Pool_Filesystem_Nfsbase_Uuid=b8ca41cb-3469-4f74-a086-dddffe37dc2d, + * Pool_Filesystem_Uuid=0004fb0000050000e70fbddeb802208f} + */ + private List<String> validRoles = new ArrayList<String>() { + { + add("utility"); + add("xen"); + } + }; + private Boolean _poolDisc = false; + public Map<String, String> poolFileSystem = new HashMap<String, String>(); + public List<String> poolIps = new ArrayList<String>(); + private List<String> poolRoles = new ArrayList<String>(); + public List<String> poolMembers = new ArrayList<String>(); + public String poolMasterVip; + public String poolAlias; + public String poolId = ""; + + public Pool(Connection c) throws ParserConfigurationException, IOException, + Exception { + client = c; + discoverServerPool(); + } + + public String getPoolMasterVip() { + return this.poolMasterVip; + } + + public String getPoolAlias() { + return this.poolAlias; + } + + public String getPoolId() { + return this.poolId; + } + + /* TODO: check the toString for the list x,x */ + public List<String> getValidRoles() { + return this.validRoles; + } + + public void setPoolIps(List<String> ips) { + this.poolIps = new ArrayList<String>(); + this.poolIps.addAll(ips); + } + + /* + * create_server_pool, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: pool_alias - default: None argument: + * pool_uuid - default: None argument: pool_virtual_ip - default: None + * argument: node_number - default: None argument: server_hostname - + * default: None argument: server_ip - default: None argument: roles - + * default: None + */ + public Boolean createServerPool(String alias, String id, String vip, + int num, String name, String ip, List<String> roles) + throws XmlRpcException { + String role = roles.toString(); + role = "xen,utility"; + Object x = callWrapper("create_server_pool", alias, id, vip, num, name, + ip, + role); + if (x == null) + return true; + + return false; + } + + public Boolean createServerPool(String alias, String id, String vip, + int num, String name, String ip) throws XmlRpcException { + return this.createServerPool(alias, + id, + vip, + num, + name, + ip, + getValidRoles()); + } + public Boolean createServerPool(int num, String name, String ip) + throws XmlRpcException { + return createServerPool(poolAlias, poolId, poolMasterVip, num, name, + ip, poolRoles); + } + + /* + * update_pool_virtual_ip, <class 'agent.api.serverpool.ServerPool'> + * argument: self - default: None argument: new_pool_vip - default: None + */ + public Boolean updatePoolVirtualIp(String ip) throws XmlRpcException { + Object x = callWrapper("update_pool_virtual_ip", ip); + if (x == null) { + this.poolMasterVip = ip; + return true; + } + return false; + } + + /* + * leave_server_pool, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: pool_uuid - default: None + */ + public Boolean leaveServerPool(String uuid) throws XmlRpcException { + Object x = callWrapper("leave_server_pool", uuid); + if (x == null) + return true; + return false; + } + + /* + * set_server_pool_alias, <class 'agent.api.serverpool.ServerPool'> + * argument: self - default: None argument: pool_alias - default: None + */ + public Boolean setServerPoolAlias(String alias) throws XmlRpcException { + Object x = callWrapper("set_server_pool_alias", alias); + if (x == null) { + this.poolAlias = alias; + return true; + } + return false; + } + + /* + * take_ownership, <class 'agent.api.serverpool.ServerPool'> argument: self + * - default: None argument: manager_uuid - default: None argument: + * manager_core_api_url - default: None + * take_ownership('0004fb00000100000af70d20dcce7d65', + * 'https://2f55e3b9efa6f067ad54a7b144bb6f2e: + * ******@0.0.0.0:7002/ovm/core/OVMManagerCoreServlet') + */ + public Boolean takeOwnership(String uuid, String apiurl) + throws XmlRpcException { + Object x = callWrapper("take_ownership", uuid, apiurl); + if (x == null) { + return true; + } + return false; + } + + /* + * destroy_server_pool, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: pool_uuid - default: None + */ + public Boolean destroyServerPool(String uuid) throws XmlRpcException { + Object x = callWrapper("destroy_server_pool", uuid); + if (x == null) { + return true; + } + return false; + } + + /* + * release_ownership, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: manager_uuid - default: None + */ + public Boolean releaseOwnership(String uuid) throws XmlRpcException { + Object x = callWrapper("release_ownership", uuid); + if (x == null) { + return true; + } + return false; + } + + /* server.discover_pool_filesystem */ + /* + * discover_server_pool, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None + */ + public Boolean discoverServerPool() throws ParserConfigurationException, + IOException, Exception { + /* forcefull rediscover for now */ + if (this._poolDisc) { + return true; + } + Object x = callWrapper("discover_server_pool"); + if (x == null) { + return false; + } + + try { + Document xmlDocument = prepParse((String) x); + String path = "//Discover_Server_Pool_Result/Server_Pool"; + this.poolId = xmlToString(path + "/Unique_Id", xmlDocument); + this.poolAlias = xmlToString(path + "/Pool_Alias", xmlDocument); + this.poolMasterVip = xmlToString(path + "/Master_Virtual_Ip", + xmlDocument); + this.poolMembers = xmlToList(path + "/Member_List", xmlDocument); + this.poolIps + .addAll(xmlToList(path + "//Registered_IP", xmlDocument)); + this._poolDisc = true; + } catch (Exception e) { + if (e.getMessage() == null) { + System.err.println("No pool to discover: " + e.getMessage()); + } else { + System.err.println("Error in pooldiscovery: " + e.getMessage()); + } + } + + return true; + } + + /* + * update_server_roles, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: roles - default: None ?> list or sring + */ + private Boolean validPoolRole(String role) throws Exception { + for (String r : this.validRoles) { + if (r.contentEquals(role)) { + return true; + } + } + throw new Exception("Illegal role: " + role); + } + + private Boolean validPoolRole(List<String> roles) throws Exception { + for (String r : roles) { + return validPoolRole(r); + } + return false; + } + + public Boolean setServerRoles() throws XmlRpcException, Exception { + validPoolRole(this.poolRoles); + String roles = StringUtils.join(this.poolRoles.toArray(), ","); + Object x = callWrapper("update_server_roles", roles); + if (x == null) + return true; + + return false; + } + + /* do some sanity check on the valid poolroles */ + public Boolean setServerRoles(List<String> roles) throws Exception { + this.poolRoles.addAll(roles); + return setServerRoles(); + } + + + public void addServerRole(String role) throws Exception { + validPoolRole(role); + this.poolRoles.add(role); + } + + public void removeServerRole(String role) { + this.poolRoles.remove(role); + } + + public boolean serverHasRole(String role) { + for (String r : this.poolRoles) { + if (r.contentEquals(role)) { + return true; + } + } + return false; + } + + /* + * join_server_pool, <class 'agent.api.serverpool.ServerPool'> argument: + * self - default: None argument: pool_alias - default: None argument: + * pool_uuid - default: None argument: pool_virtual_ip - default: None + * argument: node_number - default: None argument: server_hostname - + * default: None argument: server_ip - default: None argument: roles - + * default: None + */ + /* allow these to be set before ? */ + public Boolean joinServerPool(String alias, String id, String vip, int num, + String name, String ip, List<String> roles) throws XmlRpcException { + String role = StringUtils.join(roles.toArray(), ","); + Object x = callWrapper("join_server_pool", alias, id, vip, num, name, + ip, + role); + if (x == null) + return true; + + return false; + } + + public Boolean joinServerPool(String alias, String id, String vip, int num, + String name, String ip) throws XmlRpcException { + return joinServerPool(alias, id, vip, num, name, ip, getValidRoles()); + } + + public Boolean joinServerPool(int num, String name, String ip) + throws XmlRpcException { + return joinServerPool(poolAlias, poolId, poolMasterVip, num, name, ip, + poolRoles); + } + + /* + * set_pool_member_ip_list, <class 'agent.api.serverpool.ServerPool'> + * argument: self - default: None argument: ip_list - default: None + */ + public Boolean setPoolMemberIpList() throws XmlRpcException { + // should throw exception if no poolIps set + Object x = callWrapper("set_pool_member_ip_list", this.poolIps); + if (x == null) + return true; + + return false; + } + + public List getPoolMemberIpList() throws XmlRpcException, Exception { + if (poolIps.size() == 0) { + this.discoverServerPool(); + } + return poolIps; + } + + /* TODO: need to change the logic here */ + public Boolean setPoolMemberIpList(String ip) throws XmlRpcException { + this.poolIps = new ArrayList<String>(); + this.poolIps.add(ip); + return setPoolMemberIpList(); + } + + public Boolean addPoolMemberIp(String ip) throws XmlRpcException, Exception { + this.getPoolMemberIpList(); + this.poolIps.add(ip); + return setPoolMemberIpList(); + } + + /* meh */ + public Boolean removePoolMemberIp(String ip) throws XmlRpcException, + Exception { + this.getPoolMemberIpList(); + this.poolIps.remove(ip); + return setPoolMemberIpList(); + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/PoolOCFS2.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/PoolOCFS2.java new file mode 100644 index 0000000..1759224 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/PoolOCFS2.java
@@ -0,0 +1,157 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; + +/* should ingest this into Pool */ +public class PoolOCFS2 extends OvmObject { + public Map<String, String> poolFileSystem = new HashMap<String, String>(); + public String poolFsTarget; + public String poolFsType; + public String poolFsNFSBaseId; + public String poolFsId; + + public String poolFsNFSBaseId() { + return this.poolFsNFSBaseId; + } + + public String poolFsId() { + return this.poolFsId; + } + + public String poolFsUuid() { + return this.poolFsId; + } + + public String poolFsTarget() { + return this.poolFsTarget; + } + + public PoolOCFS2(Connection c) { + client = c; + } + + /* + * destroy_pool_filesystem, <class 'agent.api.poolfs.ocfs2.PoolOCFS2'> + * argument: self - default: None argument: poolfs_type - default: None + * argument: poolfs_target - default: None argument: poolfs_uuid - default: + * None argument: poolfs_nfsbase_uuid - default: None + */ + public Boolean destroyPoolFs(String type, String target, String uuid, + String nfsbaseuuid) throws ParserConfigurationException, + IOException, Exception { + // should throw exception if no poolIps set + Object x = callWrapper("destroy_pool_filesystem", type, target, uuid, + nfsbaseuuid); + if (x == null) + return true; + + return false; + } + + public Boolean destroyPoolFs() throws ParserConfigurationException, + IOException, Exception { + // should throw exception if no poolIps set + Object x = callWrapper("destroy_pool_filesystem", poolFsType, + poolFsTarget, poolFsId, poolFsNFSBaseId); + if (x == null) + return true; + + return false; + } + + /* + * create_pool_filesystem, <class 'agent.api.poolfs.ocfs2.PoolOCFS2'> + * argument: self - default: None argument: poolfs_type - default: None + * argument: poolfs_target - default: None argument: cluster_name - default: + * None argument: poolfs_uuid - default: None argument: poolfs_nfsbase_uuid + * - default: None argument: manager_uuid - default: None argument: + * pool_uuid - default: None argument: block_size - default: None argument: + * cluster_size - default: None argument: journal_size - default: None + */ + /* + * create_pool_filesystem('nfs', 'cs-mgmt:/volumes/cs-data/secondary', + * 'ba9aaf00ae5e2d73', '0004fb0000050000e70fbddeb802208f', + * 'b8ca41cb-3469-4f74-a086-dddffe37dc2d', + * '0004fb00000100000af70d20dcce7d65', '0004fb0000020000ba9aaf00ae5e2d73') + */ + public Boolean createPoolFs(String type, String target, String clustername, + String fsid, String nfsbaseid, String managerid, String id) + throws XmlRpcException { + Object x = callWrapper("create_pool_filesystem", type, target, + clustername, fsid, nfsbaseid, managerid, id); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + public Boolean createPoolFs(String type, String target, String clustername, + String fsid, String nfsbaseid, String managerid, String id, + int blocksize, int clustersize, int journalsize) + throws XmlRpcException { + Object x = callWrapper("create_pool_filesystem", type, target, + clustername, fsid, nfsbaseid, managerid, id, blocksize, + clustersize, journalsize); + if (x == null) + return true; + + return false; + } + + /* + * discover_pool_filesystem, <class 'agent.api.poolfs.ocfs2.PoolOCFS2'> + * argument: self - default: None + */ + public Boolean discoverPoolFs() throws ParserConfigurationException, + IOException, Exception { + // should throw exception if no poolIps set + Object x = callWrapper("discover_pool_filesystem"); + Document xmlDocument = prepParse((String) x); + String path = "//Discover_Pool_Filesystem_Result"; + poolFileSystem = xmlToMap(path + "/Pool_Filesystem", xmlDocument); + poolFsTarget = poolFileSystem.get("Pool_Filesystem_Target"); + poolFsType = poolFileSystem.get("Pool_Filesystem_Type"); + poolFsNFSBaseId = poolFileSystem.get("Pool_Filesystem_Nfsbase_Uuid"); + poolFsId = poolFileSystem.get("Pool_Filesystem_Uuid"); + if (x == null) + return true; + + return false; + } + + /* + * ocfs2_get_meta_data, <class 'agent.api.poolfs.ocfs2.PoolOCFS2'> argument: + * self - default: None argument: device - default: None argument: filename + * - default: None + */ + public Boolean ocfs2GetMetaData(String device, String filename) + throws XmlRpcException { + Object x = callWrapper("ocfs2_get_meta_data", device, filename); + // System.out.println(x); + if (x == null) + return true; + + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Remote.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Remote.java new file mode 100644 index 0000000..a2ae0a4 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Remote.java
@@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import org.apache.xmlrpc.XmlRpcException; + +/* + * should become an interface implementation + */ +public class Remote extends OvmObject { + + public Remote(Connection c) { + client = c; + } + + /* + * sys_shutdown, <class + * 'agent.api.remote.linux_remote.LinuxRemoteManagement'> argument: self - + * default: None + */ + public Boolean sysShutdown() throws XmlRpcException { + Object x = callWrapper("sys_shutdown"); + if (x == null) + return true; + + return false; + } + + /* + * remote_power_off, <class + * 'agent.api.remote.linux_remote.LinuxRemoteManagement'> argument: self - + * default: None argument: controller_type - default: None ?> figure this + * one out in the source argument: tgt_host - default: None argument: + * bmc_username - default: None argument: bmc_password - default: None + */ + + /* + * sys_reboot, <class 'agent.api.remote.linux_remote.LinuxRemoteManagement'> + * argument: self - default: None + */ + public Boolean sysReboot() throws XmlRpcException { + Object x = callWrapper("sys_reboot"); + if (x == null) + return true; + + return false; + } + + /* + * remote_power_on, <class + * 'agent.api.remote.linux_remote.LinuxRemoteManagement'> argument: self - + * default: None argument: controller_type - default: None ?> same here + * argument: tgt - default: None argument: arg1 - default: None argument: + * arg2 - default: None + */ + +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Repository.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Repository.java new file mode 100644 index 0000000..d45f198 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Repository.java
@@ -0,0 +1,205 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +/* + * should become an interface implementation + */ +public class Repository extends OvmObject { + + public Repository(Connection c) { + client = c; + } + + /* + * delete_repository, <class 'agent.api.repository.Repository'> argument: + * repo_uuid - default: None argument: erase - default: None + */ + public Boolean deleteRepo(String id, Boolean erase) throws XmlRpcException { + Object x = callWrapper("delete_repository", id, erase); + if (x == null) + return true; + + return false; + } + + /* + * import_virtual_disk, <class 'agent.api.repository.Repository'> argument: + * url - default: None argument: virtual_disk_id - default: None argument: + * repo_uuid - default: None argument: option - default: None + */ + /* should add timeout ? */ + public Boolean importVirtualDisk(String url, String vdiskid, String repoid, + String option) throws XmlRpcException { + Object x = callWrapper("import_virtual_disk", url, vdiskid, repoid, option); + if (x == null) + return true; + + return false; + } + public Boolean importVirtualDisk(String url, String vdiskid, String repoid) throws XmlRpcException { + Object x = callWrapper("import_virtual_disk", url, vdiskid, repoid); + if (x == null) + return true; + + return false; + } + + /* + * discover_repositories, <class 'agent.api.repository.Repository'> + * argument: args - default: None + */ + /* + * args are repo ids <Discover_Repositories_Result> <RepositoryList/> + * </Discover_Repositories_Result> + */ + public Boolean discoverRepo(Map<String, String> args) + throws XmlRpcException { + Object x = callWrapper("discover_repositories", args); + if (x == null) + return true; + + return false; + } + + public Boolean discoverRepo(String id) throws XmlRpcException { + Object x = callWrapper("discover_repositories", id); + if (x == null) + return true; + + return false; + } + + /* + * add_repository, <class 'agent.api.repository.Repository'> argument: + * fs_location - default: None argument: mount_point - default: None + */ + public Boolean addRepo(String remote, String local) throws XmlRpcException { + Object x = callWrapper("add_repository", remote, local); + if (x == null) + return true; + + return false; + } + + /* + * get_repository_meta_data, <class 'agent.api.repository.Repository'> + * argument: repo_mount_point - default: None + */ + public Boolean getRepoMetaData(String local) throws XmlRpcException { + Object x = callWrapper("get_repository_meta_data", local); + if (x == null) + return true; + + return false; + } + + /* + * mount_repository_fs, <class 'agent.api.repository.Repository'> argument: + * fs_location - default: None argument: mount_point - default: None + */ + public Boolean mountRepoFs(String remote, String local) + throws XmlRpcException { + Object x = callWrapper("mount_repository_fs", remote, local); + if (x == null) + return true; + + return false; + } + + /* + * unmount_repository_fs, <class 'agent.api.repository.Repository'> + * argument: mount_point - default: None + */ + public Boolean unmountRepoFs(String local) throws XmlRpcException { + Object x = callWrapper("unmount_repository_fs", local); + if (x == null) + return true; + + return false; + } + + /* + * create_repository, <class 'agent.api.repository.Repository'> argument: + * fs_location - default: None argument: mount_point - default: None + * argument: repo_uuid - default: None argument: repo_alias - default: None + */ + public Boolean createRepo(String remote, String local, String repoid, + String repoalias) throws XmlRpcException { + Object x = callWrapper("create_repository", remote, local, repoid, + repoalias); + if (x == null) + return true; + + return false; + } + + /* + * discover_repository_db, <class 'agent.api.repository.Repository'> + * <Discover_Repository_Db_Result> <RepositoryDbList> <Repository + * Uuid="0004fb0000030000aeaca859e4a8f8c0"> + * <Fs_location>cs-mgmt:/volumes/cs-data/primary</Fs_location> + * <Mount_point>/ + * OVS/Repositories/0004fb0000030000aeaca859e4a8f8c0</Mount_point> + * <Filesystem_type>nfs</Filesystem_type> <Version>3.0</Version> + * <Alias>MyRepo</Alias> + * <Manager_uuid>0004fb00000100000af70d20dcce7d65</Manager_uuid> + * <Status>Unmounted</Status> </Repository> <Repository> ... </Repository> + * </RepositoryDbList> </Discover_Repository_Db_Result> + */ + public Boolean discoverRepoDb() throws XmlRpcException { + Object x = callWrapper("discover_repository_db"); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + /* + * edit_repository_db, <class 'agent.api.repository.Repository'> argument: + * repo_uuid - default: None argument: db_changes - default: None + */ + public Boolean editRepoDb(String repoId, Map<String, String> changes) + throws XmlRpcException { + Object x = callWrapper("edit_repository_db", repoId, changes); + if (x == null) + return true; + + return false; + } + + /* + * import_ISO, <class 'agent.api.repository.Repository'> argument: url - + * default: None argument: iso_id - default: None argument: repo_uuid - + * default: None argument: option - default: None ?> it throws an error when + * you add this... + */ + /* + * is async, need to find a way to do something with that.... add timeout + * too + */ + public Boolean importIso(String url, String isoId, String repoId, + String option) throws XmlRpcException { + Object x = callWrapper("import_ISO", url, isoId, repoId); + if (x == null) + return true; + + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/RpcTypeFactory.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/RpcTypeFactory.java new file mode 100644 index 0000000..240efef --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/RpcTypeFactory.java
@@ -0,0 +1,92 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +/* + * Dealing with nil..... -sigh- + * http://libjack.com/2009/03/26/java-magento-xmlrpc-api-nil-issue/ + * + * i8 - aka long + */ + +package com.cloud.hypervisor.ovm3.object; + +import org.apache.ws.commons.util.NamespaceContextImpl; +import org.apache.xmlrpc.common.TypeFactoryImpl; +import org.apache.xmlrpc.common.XmlRpcController; +import org.apache.xmlrpc.common.XmlRpcStreamConfig; +import org.apache.xmlrpc.parser.NullParser; +import org.apache.xmlrpc.parser.TypeParser; +import org.apache.xmlrpc.parser.AtomicParser; +import org.apache.xmlrpc.serializer.NullSerializer; +import org.apache.xmlrpc.serializer.TypeSerializer; +import org.apache.xmlrpc.serializer.TypeSerializerImpl; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.ContentHandler; + +public class RpcTypeFactory extends TypeFactoryImpl { + + public RpcTypeFactory(XmlRpcController pController) { + super(pController); + } + + @Override + public TypeParser getParser(XmlRpcStreamConfig pConfig, + NamespaceContextImpl pContext, String pURI, String pLocalName) { + if ("".equals(pURI) && NullSerializer.NIL_TAG.equals(pLocalName)) { + return new NullParser(); + } else if (pLocalName.equals("i8")) { + return new LongTypeParser(); + } else { + return super.getParser(pConfig, pContext, pURI, pLocalName); + } + } + + public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig, + Object pObject) throws SAXException { + if (pObject instanceof Long) { + return new LongTypeSerializer(); + } else { + return super.getSerializer(pConfig, pObject); + } + } + + private class LongTypeSerializer extends TypeSerializerImpl { + /* + * Tag name of an i8 value. + */ + public static final String I8_TAG = "i8"; + + /* + * Fully qualified name of an i8 value. + */ + public static final String EX_I8_TAG = "i8"; + + @Override + public void write(ContentHandler pHandler, Object pObject) + throws SAXException { + write(pHandler, I8_TAG, EX_I8_TAG, pObject.toString()); + } + } + + private class LongTypeParser extends AtomicParser { + protected void setResult(String pResult) throws SAXException { + try { + super.setResult(new Long(pResult.trim())); + } catch (NumberFormatException e) { + throw new SAXParseException("Failed to parse long value: " + + pResult, getDocumentLocator()); + } + } + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/StoragePlugin.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/StoragePlugin.java new file mode 100644 index 0000000..c311523 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/StoragePlugin.java
@@ -0,0 +1,876 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xmlrpc.XmlRpcException; +import org.w3c.dom.Document; + +/* + * should become an interface implementation + */ +public class StoragePlugin extends OvmObject { + /* nfs or iscsi should be an "enabled" flag */ + /* + * storage_plugin_mount('oracle.generic.NFSPlugin.GenericNFSPlugin', { + * 'status': '', 'admin_user': '', 'admin_host': '', 'uuid': + * '0004fb00000900000c2461c2f62ba43e', 'total_sz': 0, 'admin_passwd': + * '******', 'storage_desc': '', 'free_sz': 0, 'access_host': 'cs-mgmt', + * 'storage_type': 'FileSys', 'alloc_sz': 0, 'access_grps': [], 'used_sz': + * 0, 'name': '0004fb00000900000c2461c2f62ba43e'}, { 'status': '', 'uuid': + * 'b8ca41cb-3469-4f74-a086-dddffe37dc2d', 'ss_uuid': + * '0004fb00000900000c2461c2f62ba43e', 'size': '263166853120', 'free_sz': + * '259377299456', 'state': 1, 'access_grp_names': [], 'access_path': + * 'cs-mgmt:/volumes/cs-data/secondary', 'name': + * 'nfs:/volumes/cs-data/secondary'}, + * '/nfsmnt/b8ca41cb-3469-4f74-a086-dddffe37dc2d', '', True, []) + */ + private String pluginType = "oracle.generic.NFSPlugin.GenericNFSPlugin"; + + /* TODO: subclass */ + /* + * Json, but then it's xml... {'status': '', 'admin_user': '', 'admin_host': + * '', 'uuid': '0004fb00000900000c2461c2f62ba43e', 'total_sz': 0, + * 'admin_passwd': '******', 'storage_desc': '', 'free_sz': 0, + * 'access_host': 'cs-mgmt', 'storage_type': 'FileSys', 'alloc_sz': 0, + * 'access_grps': [], 'used_sz': 0, 'name': + * '0004fb00000900000c2461c2f62ba43e'} + */ + private Map<String, Object> baseProps = new HashMap<String, Object>() { + { + put("status", ""); /* empty */ + put("admin_user", ""); /* auth */ + put("admin_host", ""); /* auth host */ + put("uuid", ""); /* no dash uuid */ + put("total_sz", ""); + put("admin_passwd", ""); /* iscsi or fc */ + put("storage_desc", ""); /* description */ + put("free_sz", 0); + put("access_host", ""); /* remote host for fs */ + put("storage_type", "FileSys"); /* type, guess lun ? */ + put("alloc_size", 0); + put("access_groups", new ArrayList<String>()); + put("sed_size", 0); + put("name", ""); /* uuid no dashes */ + }; + }; + + public String setUuid(String val) { + this.baseProps.put("uuid", val); + return val; + } + + public String getUuid() { + return (String) this.baseProps.get("uuid"); + } + + public String setName(String val) { + this.baseProps.put("name", val); + return val; + } + + public String getName() { + return (String) this.baseProps.get("name"); + } + + public String setFsType(String val) { + this.baseProps.put("storage_type", val); + return val; + } + + public String getFsType() { + return (String) this.baseProps.get("storage_type"); + } + + public String setFsHost(String val) { + this.baseProps.put("access_host", val); + return val; + } + + public String getFsHost() { + return (String) this.baseProps.get("access_host"); + } + + public String setFsServer(String val) { + return this.setFsHost(val); + } + + public String getFsServer() { + return this.getFsHost(); + } + + /* TODO: subclass */ + /* + * Meh {'status': '', 'uuid': 'b8ca41cb-3469-4f74-a086-dddffe37dc2d', + * 'ss_uuid': '0004fb00000900000c2461c2f62ba43e', 'size': '263166853120', + * 'free_sz': '259377299456', 'state': 1, 'access_grp_names': [], + * 'access_path': 'cs-mgmt:/volumes/cs-data/secondary', 'name': + * 'nfs:/volumes/cs-data/secondary'} + */ + private Map<String, Object> ssProps = new HashMap<String, Object>() { + { + put("status", ""); /* empty */ + put("uuid", ""); /* with dashes */ + put("ss_uuid", ""); /* no dashes */ + put("size", ""); + put("free_sz", ""); + put("state", 1); /* guess this is active ? */ + put("access_grp_names", new ArrayList<String>()); + put("access_path", ""); /* remote path */ + put("name", ""); /* just a name */ + put("mount_options", new ArrayList<String>()); /* + * array of values + * which match normal + * mount options + */ + }; + }; + + public String setFsSourcePath(String val) { + this.ssProps.put("access_path", val); + return val; + } + + public String getFsSourcePath() { + return (String) this.ssProps.get("access_path"); + } + + public String setMntUuid(String val) { + this.ssProps.put("uuid", val); + return val; + } + + public String getMntUuid() { + return (String) this.ssProps.get("uuid"); + } + + public String setSsUuid(String val) { + this.ssProps.put("ss_uuid", val); + return val; + } + + public String getSsUuid() { + return (String) this.ssProps.get("ss_uuid"); + } + + public String setSsName(String val) { + this.ssProps.put("name", val); + return val; + } + + public String getSsName() { + return (String) this.ssProps.get("ss_uuid"); + } + + public String getFreeSize() { + return this.ssProps.get("free_sz").toString(); + } + + public String getTotalSize() { + return this.ssProps.get("size").toString(); + } + + public String getSize() { + return this.ssProps.get("size").toString(); + } + + /* TODO: subclass */ + /* {'fr_type': 'File', + 'ondisk_sz': '48193536', + 'fs_uuid': '7718562d-872f-47a7-b454-8f9cac4ffa3a', + 'file_path': '/nfsmnt/7718562d-872f-47a7-b454-8f9cac4ffa3a/0004fb0000060000d4a1d2ec05a5e799.img', + 'file_sz': '52380672'} + */ + private Map<String, Object> fileProps = new HashMap<String, Object>() { + { + put("fr_type", ""); + put("ondisk_sz", ""); + put("fs_uuid", ""); + put("file_path", ""); + put("file_sz", ""); + } + }; + + public String getFileName() { + return (String) this.fileProps.get("file_path"); + } + public long getFileSize() { + return Long.parseLong((String) this.fileProps.get("file_sz")); + } + private String mountPoint = ""; + + public String setFsMountPoint(String val) { + this.mountPoint = val; + return val; + } + + public String getFsMountPoint() { + return mountPoint; + } + + public String unknown = ""; /* empty */ + public Boolean active = true; + public List<String> someList = new ArrayList<String>(); /* empty */ + + public StoragePlugin(Connection c) { + client = c; + } + + /* + * 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 + */ + + /* TODO: make more generic now only for files + * storage_plugin_create, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + * - calls resize secretly.. after "create" + */ + public Boolean storagePluginCreate(String poolUuid, String host, + String file, Long size) throws XmlRpcException { + /* this is correct ordering stuff */ + String uuid = this.deDash(poolUuid); + ssProps.put("uuid", uuid); + ssProps.put("access_host", host); + ssProps.put("storage_type", "FileSys"); + ssProps.put("name", ""); + ssProps.put("status", ""); + ssProps.put("admin_user", ""); + ssProps.put("admin_passwd", ""); + ssProps.put("admin_host", ""); + ssProps.put("total_sz", ""); + ssProps.put("free_sz", ""); + ssProps.put("used_sz", ""); + ssProps.put("access_grps", ""); + ssProps.put("storage_desc", ""); + + baseProps.put("ss_uuid", uuid); + baseProps.put("state", 2); + baseProps.put("uuid", poolUuid); + /* some more bogus values */ + baseProps.put("status", ""); + baseProps.put("access_path", ""); + baseProps.put("access_grp_names", ""); + baseProps.put("name", ""); + baseProps.put("size", ""); + + /* + * fileProps.put("fr_type", "File"); + * fileProps.put("fs_uuid", ssuuid); + * fileProps.put("file_path", file); + * fileProps.put("file_sz", ""); + * fileProps.put("ondisk_sz", ""); + */ + Object x = (HashMap<String, Object>)callWrapper("storage_plugin_create", + this.pluginType, this.ssProps, this.baseProps, file, "File", size); + + if (x == null) + return true; + + return true; + } + + /* + * 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 type) throws XmlRpcException { + this.pluginType = type; + return storagePluginListFs(); + } + + public Boolean storagePluginListFs() throws XmlRpcException { + Map<String, String> y = new HashMap<String, String>(); + Object x = callWrapper("storage_plugin_listFileSystems", + this.pluginType, y); + if (x == null) + return true; + + return false; + } + + /* + * 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 Boolean storagePluginMount(String nfsHost, String nfsPath, + String mntUuid, String mountPoint) throws XmlRpcException { + String propUuid = this.deDash(mntUuid); + this.setUuid(propUuid); + this.setName(propUuid); + this.setFsServer(nfsHost); + this.setFsSourcePath(nfsHost + ":" + nfsPath); + this.setMntUuid(mntUuid); + this.setSsUuid(propUuid); + this.setSsName("nfs:" + nfsPath); + this.setFsMountPoint(mountPoint); + this.storagePluginMount(); + Map<String, Object> x = (Map<String, Object>) callWrapper( + "storage_plugin_mount", this.pluginType, this.baseProps, + this.ssProps, this.mountPoint, this.unknown, this.active, + this.someList); + // System.out.println(x); + if (x == null) { + return true; + } + return false; + } + + /* + * {ss_uuid=eb1dbafadee9450d876239bb5e3b7f4a, + * mount_options=[Ljava.lang.Object;@2d8dea20, status=, + * name=nfs:/volumes/cs-data/secondary, state=1, + * access_path=cs-mgmt:/volumes/cs-data/secondary, + * uuid=6ab917b0-a070-4254-8fe2-e2163ee0e885, + * access_grp_names=[Ljava.lang.Object;@4005f23d, free_sz=, size=} + */ + public Boolean storagePluginMount() throws XmlRpcException { + Map<String, Object> x = (Map<String, Object>) callWrapper( + "storage_plugin_mount", this.pluginType, this.baseProps, + this.ssProps, this.mountPoint, this.unknown, this.active, + this.someList); + // System.out.println(x); + if (x == null) { + return true; + } + // System.out.println(x); + /* + * {ss_uuid=1b8685bf625642cb92ddd4c0d7b18620, + * mount_options=[Ljava.lang.Object;@6f479e5f, status=, + * name=nfs:/volumes/cs-data/secondary, state=1, + * access_path=cs-mgmt:/volumes/cs-data/secondary, + * uuid=54d78233-508f-4632-92a6-97fc1311ca23, + * access_grp_names=[Ljava.lang.Object;@46eea80c, free_sz=, size=} + */ + + /* + * if (!x.get("ss_uuid").equals(this.ssProps.get("ss_uuid"))) { return + * false; } this.ssProps.put("mount_options", x.get("mount_options")); + * this.ssProps.put("access_grp_names", x.get("access_grp_names")); + */ + return false; + } + + /** + * . + * storage_plugin_unmount, <class 'agent.api.storageplugin.StoragePlugin'> + * argument: impl_name - default: None + * @return boolean + * @throws XmlRpcException + */ + public final Boolean storagePluginUnmount() throws XmlRpcException { + Object x = callWrapper("storage_plugin_unmount", this.pluginType, + this.baseProps, this.ssProps, this.mountPoint, this.active); + if (x == null) { + return true; + } + + return false; + } + + /* + * 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'> + */ + /* + * <Discover_Storage_Plugins_Result> <storage_plugin_info_list> + * <storage_plugin_info plugin_impl_name="oracle.ocfs2.OCFS2.OCFS2Plugin"> + * <fs_api_version>1,2,7</fs_api_version> + * <generic_plugin>False</generic_plugin> + * <plugin_version>0.1.0-38</plugin_version> + * <filesys_type>LocalFS</filesys_type> + * <extended_api_version>None</extended_api_version> <plugin_desc>Oracle + * OCFS2 File system Storage Connect Plugin</plugin_desc> + * <cluster_required>True</cluster_required> <plugin_name>Oracle OCFS2 File + * system</plugin_name> <fs_extra_info_help>None</fs_extra_info_help> + * <required_api_vers>1,2,7</required_api_vers> + * <file_extra_info_help>None</file_extra_info_help> + * <ss_extra_info_help>None</ss_extra_info_help> + * <filesys_name>ocfs2</filesys_name> <vendor_name>Oracle</vendor_name> + * <plugin_type>ifs</plugin_type> <abilities> + * <resize_is_sync>YES</resize_is_sync> <clone_is_sync>YES</clone_is_sync> + * <access_control>NO</access_control> + * <custom_clone_name>YES</custom_clone_name> + * <require_storage_name>NO</require_storage_name> + * <backing_device_type>DEVICE_SINGLE</backing_device_type> + * <splitclone_while_open>NO</splitclone_while_open> + * <custom_snap_name>YES</custom_snap_name> <snapshot>ONLINE</snapshot> + * <splitclone>UNSUPPORTED</splitclone> <snap_is_sync>YES</snap_is_sync> + * <snapclone>ONLINE</snapclone> <splitclone_is_sync>NO</splitclone_is_sync> + * <clone>ONLINE</clone> <resize>ONLINE</resize> + * <snapclone_is_sync>YES</snapclone_is_sync> </abilities> + * </storage_plugin_info> <storage_plugin_info + * plugin_impl_name="oracle.generic.SCSIPlugin.GenericPlugin"> .... + */ + public Boolean discoverStoragePlugins() + throws ParserConfigurationException, IOException, Exception { + Object result = callWrapper("discover_storage_plugins"); + // System.out.println(result); + Document xmlDocument = prepParse((String) result); + /* could be more subtle */ + String path = "//Discover_Storage_Plugins_Result/storage_plugin_info_list"; + /* + * Capabilities = xmlToMap(path+"/Capabilities", xmlDocument); VMM = + * xmlToMap(path+"/VMM", xmlDocument); NTP = xmlToMap(path+"/NTP", + * xmlDocument); Date_Time = xmlToMap(path+"/Date_Time", xmlDocument); + * Generic = xmlToMap(path, xmlDocument); + */ + if (result != null) + return true; + + return 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 + */ + + /* TODO: 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 XmlRpcException { + /* clean the props, the empty ones are checked, but not for content... */ + // String uuid = this.deDash(poolUuid); + baseProps.put("uuid", ""); + baseProps.put("access_host", ""); + baseProps.put("storage_type", "FileSys"); + ssProps.put("ss_uuid", ""); + ssProps.put("access_path", ""); + ssProps.put("uuid", poolUuid); + fileProps.put("fr_type", "File"); + fileProps.put("fs_uuid", poolUuid); + fileProps.put("file_path", file); + fileProps.put("file_sz", ""); + fileProps.put("ondisk_sz", ""); + Object x = (HashMap<String, Object>) callWrapper( + "storage_plugin_destroy", this.pluginType, this.baseProps, + this.ssProps, this.fileProps); + if (x == null) + return true; + + return false; + } + + public Boolean storagePluginDestroy() throws XmlRpcException { + /* clean the props */ + Object x = (HashMap<String, Object>) callWrapper( + "storage_plugin_destroy", this.pluginType, this.baseProps, + this.ssProps, this.fileProps); + if (x == null) + return true; + + return false; + } + + /* + * storage_plugin_isSnapable, <class + * 'agent.api.storageplugin.StoragePlugin'> argument: impl_name - default: + * None + */ + + /* + * storage_plugin_getStorageServerInfo, <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 Boolean storagePluginGetFileInfo() throws XmlRpcException { + fileProps = (HashMap<String, Object>)callWrapper("storage_plugin_getFileInfo", + this.pluginType, this.baseProps, this.fileProps); + if (fileProps == null) + return true; + + return false; + } + + public Boolean storagePluginGetFileInfo(String file) throws XmlRpcException { + fileProps.put("file_path", file); + fileProps = (HashMap<String, Object>)callWrapper("storage_plugin_getFileInfo", + this.pluginType, + this.ssProps, + this.baseProps, + this.fileProps); + if (fileProps == null) + return true; + + return false; + } + + public Boolean storagePluginGetFileInfo(String poolUuid, String host, + String file) throws XmlRpcException { + /* file path is the full path */ + String uuid = this.deDash(poolUuid); + baseProps.put("uuid", poolUuid); + baseProps.put("access_host", host); + ssProps.put("access_path", ""); + ssProps.put("uuid", uuid); + ssProps.put("state", 1); + ssProps.put("ss_uuid", poolUuid); + ssProps.put("name", ""); + fileProps.put("file_path", file); + fileProps = (HashMap<String, Object>)callWrapper("storage_plugin_getFileInfo", + this.pluginType, + this.ssProps, + this.baseProps, + this.fileProps); + if (fileProps == null) + return true; + + return false; + } + + /* TODO: 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 Boolean storagePluginGetFileSystemInfo(String propUuid, + String mntUuid, String nfsHost, String nfsPath) + throws XmlRpcException { + /* clean the props */ + this.setUuid(propUuid); + this.setSsUuid(propUuid); + this.setMntUuid(mntUuid); + this.setFsHost(nfsHost); + this.setFsSourcePath(nfsHost + ":" + nfsPath); + this.setFsType("FileSys"); + Map<String, Object> props = (HashMap<String, Object>) callWrapper( + "storage_plugin_getFileSystemInfo", this.pluginType, + this.baseProps, this.ssProps); + this.ssProps = props; + if (props == null) + return false; + + return true; + } + + /* TODO: double check base and ss ordering!!!! */ + public Boolean storagePluginGetFileSystemInfo() throws XmlRpcException { + HashMap<String, Object> props = (HashMap<String, Object>) callWrapper( + "storage_plugin_getFileSystemInfo", this.pluginType, + this.baseProps, this.ssProps); + this.ssProps = props; + // System.out.println(props); + if (props == null) + return false; + + return true; + } + + /* + * 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 + */ + /* should really make that stuff a class as this is weird now... */ + public Boolean storagePluginListMounts() throws XmlRpcException { + Object x = callWrapper("storage_plugin_listMountPoints", + this.pluginType, this.baseProps); + if (x == null) + return true; + + return false; + } + + public Boolean storagePluginListMounts(String uuid) throws XmlRpcException { + /* should allow for putting in the uuid */ + Object x = callWrapper("storage_plugin_listMountPoints", + this.pluginType, this.baseProps); + if (x == null) + return true; + + return false; + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Test.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Test.java new file mode 100644 index 0000000..850daf8 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Test.java
@@ -0,0 +1,546 @@ +/******************************************************************************* + * 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.cloud.hypervisor.ovm3.object; + +// import java.io.File; +import java.math.BigInteger; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.UUID; + + +import java.util.Map.Entry; + +// mport org.apache.commons.io.FileUtils; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.hypervisor.ovm3.object.Linux.FileSystem; + +public class Test { + // private static Sanitize _insane = new Sanitize(); + /* + * Other trinket + * https://192.168.1.51:7002/ovm/core/OVMManagerCoreServlet&c=1 + * &s=-1&lb=p&t=2 + * &p=1dd5e891d9d0edbd81c2a69ab3d1b7ea%2C2f3b7fca202045058ae388d22f21f508' + */ + public static void main(final String[] args) throws Exception { + boolean CheckNet = false; + boolean CheckNtp = false; + boolean CheckLinux = false; + boolean CheckCommon = false; + boolean CheckCluster = false; + boolean CheckRepo = false; + boolean CheckPool = false; + boolean CheckOcfs2 = false; + boolean CheckNFSPlugin = false; + boolean CheckXen = false; + boolean CheckVnc = false; + + boolean CheckCombine = false; + boolean CheckVmInfo = false; + boolean CheckUuid = false; + boolean CheckBridge = false; + boolean CheckFs = false; + boolean CheckPlugin = true; + + + try { + Connection c; + Socket client; + String hostname = "ovm-2"; + try{ + client = new Socket(hostname, 8899); + } catch (Exception e) { + hostname = "localhost"; + client = new Socket(hostname, 8899); + } + if (!client.isConnected()) { + System.out.println("No connection"); + } else { + System.out.println("connected to: " + hostname); + } + client.close(); + try { + System.out.println("trying to connect to " + hostname); + c = new Connection(hostname, 8899, "oracle", "test123"); + } catch (Exception e) { + throw new Exception("Unable to connect to " + hostname + + " port seemed to listen..."); + } + /* + * needs to be finished and implement ovs + bridge, or do we count + * on chef ? + */ + if (CheckPlugin) { + CloudStackPlugin csp = new CloudStackPlugin(c); + try { + System.out.println(csp.ovsUploadSshKey("test", "testing 123")); +// FileUtils.readFileToString(new File("")))); + String ip = "169.254.1.202"; + String domain = "i-2-29-VM"; + String pubnic = "bond0"; + // System.out.println(csp.ovsDom0Stats(pubnic)); + // System.out.println(csp.domrCheckPort(ip, 3922, 3, 3)); + // System.out.println(csp.domrCheckSsh(ip)); + System.out.println("vnc Port: "+ csp.getVncPort(domain)); + // System.out.println(csp.domrExec(ip, "ls -l").getStdOut()); + Map<String, String> stats = csp.ovsDomUStats(domain); + /* for (final Entry<String, String> stat : stats.entrySet()) { + System.out.println(stat.getKey() + " " + + Double.parseDouble(stat.getValue())); + } */ + Thread.sleep(1000); + Map<String, String> stats2 = csp.ovsDomUStats(domain); + for (final Entry<String, String> stat : stats2.entrySet()) { + String key = stat.getKey(); + Double delta = Double.parseDouble(stat.getValue()) + - Double.parseDouble(stats.get(key)); + System.out.println(stat.getKey() + ": " + delta); + } + Integer cpus = Integer.parseInt(stats.get("vcpus")); + Double d_cpu = Double.parseDouble(stats.get("cputime")) + - Double.parseDouble(stats2.get("cputime")); + Double d_time = Double.parseDouble(stats.get("uptime")) + - Double.parseDouble(stats2.get("uptime")); + Double cpupct = d_cpu/d_time * 100 * cpus; + System.out.println(cpupct); + } catch (Exception e) { + System.out.println("nooooo!!!" + e.getMessage()); + throw new Exception(e.getMessage()); + } + } + if (CheckFs) { + Linux host = new Linux(c); + + Map<String, Linux.FileSystem> fsList = host + .getFileSystemList("nfs"); + Linux.FileSystem fs = fsList.get("nfs"); + System.out.println(fs + " " + fsList); + } + if (CheckUuid) { + System.out.println(UUID.nameUUIDFromBytes(("test@test-test") + .getBytes())); + } + if (CheckNet) { + Network net = new Network(c); + System.out.println(net.getInterfaceByName("c0a80100")); + // net.discoverNetwork(); + System.out + .println(net.getInterfaceByName("c0a80100").getAddress()); + System.out.println(net.getInterfaceByIp("192.168.1.65").getName()); + // System.out.println(bridge.getMac()); + } + if (CheckCommon == true) { + Common Com = new Common(c); + String x = Com.getApiVersion(); + System.out.println("Api Version: " + x); + String y = Com.sleep(1); + System.out.println("Sleep: " + y); + String msg = Com.echo("testing 1 2 3"); + System.out.println("Echo: " + msg); + /* + * String disp = Com.dispatch ("192.168.1.60", "hoeleboele"); + * System.out. println("dispatch" + disp); + */ + } + /* check stuff */ + if (CheckLinux == true) { + Linux Host = new Linux(c); + Host.discoverHardware(); + Host.discoverServer(); + System.out.println("hwVMM: " + Host.hwVMM.toString()); + System.out.println("hwSystem: " + Host.hwSystem.toString()); + System.out.println("Cap: " + Host.Capabilities.toString()); + System.out.println("VMM: " + Host.VMM.toString()); + System.out.println("NTP: " + Host.NTP.toString()); + System.out.println("DT: " + Host.DateTime.toString()); + System.out.println("Gen: " + Host.Generic.toString()); + System.out.println("time; " + Host.getDateTime()); + // needs to be within bounds of 1970... *grin* + System.out.println("update time to 1999: " + + Host.setDateTime(1999, 12, 31, 12, 0, 0)); + System.out.println("lastboot: " + Host.getLastBootTime()); + System.out.println("time: " + Host.localTime); + Calendar now = Calendar.getInstance(); + int year = now.get(Calendar.YEAR); + int month = now.get(Calendar.MONTH); // Note: zero based! + int day = now.get(Calendar.DAY_OF_MONTH); + int hour = now.get(Calendar.HOUR_OF_DAY); + int minute = now.get(Calendar.MINUTE); + int second = now.get(Calendar.SECOND); + int millis = now.get(Calendar.MILLISECOND); + System.out.println("set time to now: " + + Host.setDateTime(year, month, day, hour, minute, + second)); + System.out.println("lastboot: " + Host.getLastBootTime()); + System.out.println("time: " + Host.localTime); + System.out.println("update password: " + + Host.updateAgentPassword("oracle", "test123")); + System.out.println("set time zone: " + + Host.setTimeZone("Europe/London", false)); + System.out.println("time zone: " + Host.getTimeZone() + ", " + + Host.timeZone + ", " + Host.timeUTC); + System.out.println("set time zone: " + + Host.setTimeZone("Europe/Amsterdam", true)); + System.out.println("time zone: " + Host.getTimeZone() + ", " + + Host.timeZone + ", " + Host.timeUTC); + // System.out.println("Luns: " + Host.discoverPhysicalLuns()); + + } + + /* setting up ntp */ + if (CheckNtp == true) { + Ntp ntp = new Ntp(c); + ntp.getDetails(); + System.out.println("ntp isServer: " + ntp.isServer()); + System.out.println("ntp isRunning: " + ntp.isRunning()); + System.out.println("ntp Servers: " + ntp.servers()); + ntp.addServer("192.168.1.1"); + ntp.addServer("192.168.1.61"); + System.out.println("ntp set: " + ntp.setNtp(true)); + System.out.println("ntp enable: " + ntp.enableNtp()); + ntp.getDetails(); + System.out.println("ntp isServer: " + ntp.isServer()); + System.out.println("ntp isRunning: " + ntp.isRunning()); + System.out.println("ntp Servers: " + ntp.servers()); + System.out.println("ntp disable: " + ntp.disableNtp()); + System.out.println("ntp reset: " + ntp.setNtp("", false)); + } + + if (CheckNFSPlugin == true) { + Linux lin = new Linux(c); + lin.discoverServer(); + System.out.println(lin.getCapabilities()); + Map<String, FileSystem> fsList = lin.getFileSystemList("nfs"); + System.out.println(fsList); + System.out.println(BigInteger.valueOf(lin.getMemory() + .longValue())); + System.out.println(lin.getFreeMemory()); + BigInteger totalmem = BigInteger.valueOf(lin.getMemory() + .longValue()); + BigInteger freemem = BigInteger.valueOf(lin.getFreeMemory() + .longValue()); + System.out.println(totalmem.subtract(freemem)); + /* + * for (final Map.Entry<String, Linux.FileSystem> entry : fsList + * .entrySet()) { + * Linux.FileSystem fs = entry.getValue(); + * StoragePlugin sp = new StoragePlugin(c); + * String propUuid = sp.deDash(fs.getUuid()); + * String mntUuid = fs.getUuid(); + * String fsType = "FileSys"; + * sp.setUuid(propUuid); + * sp.setSsUuid(propUuid); + * sp.setName(propUuid); + * sp.setFsType(fsType); + * sp.setFsServer(fs.getHost()); + * sp.setFsSourcePath(fs.getDevice()); + * sp.storagePluginGetFileSystemInfo(); + * } + */ + /* + * StoragePlugin sp = new StoragePlugin(c); + * String propUuid = sp.deDash(sp.newUuid()); + * String mntUuid = sp.newUuid(); + * String nfsHost = "cs-mgmt"; + * String nfsPath = "/volumes/cs-data/primary"; + * String fsType = "FileSys"; + * sp.setUuid(propUuid); + * sp.setName(propUuid); + * sp.setFsType(fsType); + * sp.setFsServer(nfsHost); + * sp.setFsSourcePath(nfsHost + ":" + nfsPath); + * // sp.fsTarget("/nfsmnt/" + mntUuid); + * sp.setFsMountPoint("/nfsmnt/" + mntUuid); + * sp.setMntUuid(mntUuid); + * sp.setSsUuid(propUuid); + * sp.setSsName("nfs:" + nfsPath); + * if (sp.storagePluginMount() != null) { + * lin.discoverMountedFs("nfs"); + * // System.out.println(sp.extprops); + * StoragePlugin store = new StoragePlugin(c); + * store.setUuid(propUuid); + * store.setSsUuid(propUuid); + * store.setMntUuid(mntUuid); + * store.setFsHost(nfsHost); + * store.setFsSourcePath(nfsHost + ":" + nfsPath); + * // store.setFsMountPoint(pool.getPath()); + * store.storagePluginGetFileSystemInfo(); + * System.out.println(store.getTotalSize()); + * sp.setFsSourcePath(nfsHost + ":" + nfsPath); + * sp.storagePluginUnmount(); + * } + */ + } + + /* still needs to be finished! */ + if (CheckRepo == true) { + Repository repo = new Repository(c); + String repouuid = repo.deDash(repo.newUuid()); + String remote = "cs-mgmt:/volumes/cs-data/secondary"; + String local = "/OVS/Repositories/" + repouuid; + String url = "http://nibbler/~funs/iso"; + String iso = url + "/gentoo.iso"; + String vhd = url + "/ovm.raw"; + String isouuid = repo.deDash(repo.newUuid()); + String vmuuid = repo.deDash(repo.newUuid()); + + repo.mountRepoFs(remote, local); + repo.createRepo(remote, repouuid, repouuid, "My Comment"); + repo.discoverRepoDb(); + // repo.discoverRepo(repouuid); + repo.importIso(iso, isouuid + ".iso", repouuid, ""); + repo.importVirtualDisk(vhd, vmuuid + ".img", repouuid, ""); + repo.deleteRepo(repouuid, true); + repo.unmountRepoFs(local); + repo.discoverRepoDb(); + repo.discoverRepo(repouuid); + } + + if (CheckPool == true) { + System.out.println("checking pool"); + Pool pool = new Pool(c); + pool.discoverServerPool(); + System.out.println(pool.getPoolAlias()); + System.out.println(pool.getPoolId()); + if (pool.getPoolId().contentEquals("TEST")) { + System.out.println("pool equals test"); + } else { + System.out.println("pool" + pool.getPoolId()); + } + List<String> ips = new ArrayList<String>(); + ips.add("192.168.1.64"); + ips.add("192.168.1.65"); + /* + * pool.setPoolIps(ips); + * pool.setPoolMemberIpList(); + */ + /* + * if (pool.poolFsId != null) { + * pool.leaveServerPool(pool.poolFsId); + * } + */ + System.out.println("pool members: " + + pool.getPoolMemberIpList()); + } + + if (CheckOcfs2 == true) { + PoolOCFS2 poolocfs = new PoolOCFS2(c); + poolocfs.discoverPoolFs(); + // poolocfs.ocfs2GetMetaData(); + } + + if (CheckCluster == true) { + Pool pool = new Pool(c); + pool.discoverServerPool(); + Cluster Clos = new Cluster(c); + // Clos.destroyCluster(pool.poolFsId); + if (pool.getPoolId() != null) { + // Clos.deconfigureServerForCluster(pool.poolId); + } + System.out.println("Cluster online: " + Clos.isClusterOnline()); + System.out.println("Cluster discover: " + + Clos.discoverCluster()); + + } + + if (CheckXen == true) { + Xen xen = new Xen(c); + xen.listVms(); + xen.createVm("xx", "xx"); + /* xen.deleteVm(repoId, vmId); */ + } + + /* check the combination of stuff */ + if (CheckCombine == true) { + /* prepare host, mgr should have "steady uuid" */ + OvmObject Go = new OvmObject(); + String masterUuid = Go.deDash(Go.newUuid()); + + /* check capabilities */ + Linux Host = new Linux(c); + Host.discoverServer(); + /* setup pool and role, needs utility to be able to do shit */ + Pool pool = new Pool(c); + + /* Info comes from Linux, not the pool, but needs to be set in the pool -sigh- */ + if (Host.Get("Server_Roles").contentEquals( + pool.getValidRoles().toString())) { + pool.setServerRoles(pool.getValidRoles()); + } + if (Host.Get("Membership_State").contentEquals("Unowned")) { + pool.takeOwnership(masterUuid, ""); + } + /* get primary storage mounted and registered */ + + StoragePlugin sp = new StoragePlugin(c); + String propUuid = sp.deDash(sp.newUuid()); + String mntUuid = sp.newUuid(); + String nfsHost = "cs-mgmt"; + String nfsPath = "/volumes/cs-data/primary"; + String fsType = "FileSys"; + sp.setUuid(propUuid); + sp.setName(propUuid); + sp.setFsType(fsType); + sp.setFsServer(nfsHost); + sp.setFsSourcePath(nfsHost + ":" + nfsPath); + sp.setMntUuid(mntUuid); + sp.setSsUuid(propUuid); + sp.setSsName("nfs:" + nfsPath); + sp.setFsMountPoint("/nfsmnt/" + mntUuid); + + /* setup a repo */ + Repository repo = new Repository(c); + String repouuid = repo.deDash(repo.newUuid()); + String remote = "cs-mgmt:/volumes/cs-data/secondary"; + String repopath = "/OVS/Repositories/" + repouuid; + String url = "http://nibbler/~funs/iso"; + String iso = url + "/gentoo.iso"; + String vhd = url + "/ovm.raw"; + String isouuid = repo.deDash(repo.newUuid()); + String vmuuid = repo.deDash(repo.newUuid()); + + repo.discoverRepoDb(); + + repo.mountRepoFs(remote, repopath); + repo.createRepo(remote, repouuid, repouuid, "My Comment"); + repo.discoverRepoDb(); + // repo.discoverRepo(repouuid); + String isoname = isouuid + ".iso"; + String imgname = vmuuid + ".img"; + repo.importIso(iso, isoname, repouuid, ""); + repo.importVirtualDisk(vhd, imgname, repouuid, ""); + + if (sp.storagePluginMount() != null) { + /* prep the VM disk to go to primary storage */ + Linux vmDisk = new Linux(c); + String srcvmimg = repopath + "/VirtualDisks/" + imgname; + String dstvmimg = sp.getFsMountPoint() + "/" + imgname; + /* the "solving" of no real primary and secondary storage in OVS */ + vmDisk.copyFile(srcvmimg, dstvmimg); + Xen xen = new Xen(c); + + /* + * 'vfb': + * ['type=vnc,vncunused=1,vnclisten=127.0.0.1,keymap=en-us'] + */ + /* + * 'disk': [ + * 'file:/OVS/Repositories/0004fb0000030000aeaca859e4a8f8c0/VirtualDisks/0004fb0000120000c444117fd87ea251.img,xvda,w'] + */ + /* 'vif': ['mac=00:21:f6:00:00:00,bridge=c0a80100'] */ + String vmName = Go.deDash(Go.newUuid()); + + Xen.Vm vm = xen.getVmConfig(); + vm.setVmName(vmName); + vm.setVmUuid(vmName); + + vm.addRootDisk(dstvmimg); + + vm.addVif(0, "c0a80100", "00:21:f6:00:00:02"); + vm.setVnc("0.0.0.0"); + xen.createVm(repouuid, vm.vmName); + xen.startVm(repouuid, vm.vmName); + /* + * vm.stopVm(repouuid, vm.vmUuid); vm.deleteVm(repouuid, + * vm.vmUuid); + */ + System.out.println("Created VM with: " + vmName); + System.out.println("repo: " + repouuid); + System.out.println("image: " + imgname); + System.out.println("disk: " + dstvmimg); + System.out.println("master: " + masterUuid); + } + } + if (CheckVmInfo == true) { + Xen host = new Xen(c); + /* make an itterator */ + // String vmId = "14fc3846-45e5-3c08-ad23-432ceb07407b"; + // String repoId = "f12842eb-f5ed-3fe7-8da1-eb0e17f5ede8"; + String vmName = "s-1-VM"; + Xen.Vm vm = null; + Xen.Vm ovm = null; + try { + /* backwards for now: */ + ovm = host.getRunningVmConfig(vmName); + System.out.println(ovm.getVmRootDiskPoolId()); + /* new style */ + vm = host.getVmConfig(vmName); + vm.addIso("test.iso"); + if (vm.getVmUuid().equals("")) { + System.out.println("no vm found"); + } else { + System.out.println(vm.getVmParams()); + System.out.println(vm.getVmDisks()); + System.out.println(vm.getVmUuid()); + System.out.println(vm.getPrimaryPoolUuid()); + vm.removeDisk("test.iso"); + System.out.println(vm.getVmParams().get("disk")); + } + + } catch (XmlRpcException e) { + System.out.println("Failed to get VM details for " + vmName + + " on " + c.getIp()); + } + } + if (CheckVnc == true) { + Xen vms = new Xen(c); + Xen.Vm vm = vms.listVms().get("Domain-0"); + vm.setVncAddress("0.0.0.0"); + vm.setVncPassword("testikkel"); + vm.setVnc(); + System.out.println(vm._vmVnc + " " + vm.vmVnc); + } + if (CheckBridge) { + Network net = new Network(c); + for (final Map.Entry<String, Network.Interface> entry : net.getInterfaceList().entrySet()) { + Network.Interface iface = entry.getValue(); + System.out.println("interface: " + iface.getName() + ", phys: " + iface.getPhysical() + ", type: " + iface.getIfType()); + } + String physInterface = "bond0"; + Integer vlanId = 2; + String physVlanInt = physInterface + "." + vlanId.toString(); + String brName = "c0a80100" + "." + vlanId.toString(); + System.out.println(net.getInterfaceByName(physVlanInt) + + " " + net.getInterfaceByName(brName)); + + if (net.getInterfaceByName(physVlanInt) == null) + net.startOvsVlanConfig(physInterface, vlanId); + + if (net.getInterfaceByName(brName) == null) + net.startOvsBrConfig(brName, physVlanInt); + + // net.startOvsLocalConfig("control0"); + // net.ovsBrConfig("start", "control0", "lo"); + // net.ovsIpConfig("control0", "static", "169.254.0.1", + // "255.255.0.0"); + // execOverSsh("route del -net 169.254.0.0/16"); + } + /* cleanup */ + /* + * repo.deleteRepo(repouuid, true); + * repo.unmountRepoFs(repopath); repo.discoverRepoDb(); + * repo.discoverRepo(repouuid); sp.storagePluginUnmount(); + */ + + } catch (Exception e) { + // TODO Auto-generated catch block + e.getMessage(); + } + } +}
diff --git a/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Xen.java b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Xen.java new file mode 100644 index 0000000..7d30cab --- /dev/null +++ b/plugins/hypervisors/ovm3/src/com/cloud/hypervisor/ovm3/object/Xen.java
@@ -0,0 +1,1169 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +/* contains VM related stuff too */ + +package com.cloud.hypervisor.ovm3.object; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.apache.xmlrpc.XmlRpcException; +// import org.w3c.dom.Document; + +/* + * should become an interface implementation + */ +public class Xen extends OvmObject { + public Xen(Connection c) { + client = c; + } + + private Map<String, Vm> vmList = null; + + /* + * ugly for now, but just insert a "default" VM in the Xen class will strip + * it out later if we need to + */ + private Vm vm = new Vm(); + + /* a vm class.... + * Setting up a VM is different than retrieving one from OVM. + * retrieve with list: + * {state=-b----, vcpus=1, on_poweroff=destroy, cpu_weight=27500, cpus=[Ljava.lang.Object;@4239410a, cpu_cap=0, on_xend_start=ignore, description=, name=0d87b9506da945fd98fb979bb345c187, features=, bootloader_args=-q, shadow_memory=0, domid=7, pool_name=Pool-0, maxmem=256, store_mfn=873241, console_mfn=873240, status=2, builder=linux, image={pci=[Ljava.lang.Object;@3cdd197d, device_model=/usr/lib/xen/bin/qemu-dm, superpages=0, videoram=4, tsc_mode=0, nomigrate=0, notes=[Ljava.lang.Object;@57b47cc2, kernel=, expose_host_uuid=0}, bootloader=/usr/bin/pygrub, cpu_time=1.328733473, memory=256, on_crash=restart, online_vcpus=1, on_reboot=restart, device={console=[Ljava.lang.Object;@a6ad18a, vbd=[Ljava.lang.Object;@6ae2c05d, vkbd=[Ljava.lang.Object;@4cc3507d, vfb=[Ljava.lang.Object;@2ad965ea, vif=[Ljava.lang.Object;@26b1fba0}, start_time=1390033675.38, uuid=0d87b950-6da9-45fd-98fb-979bb345c187, on_xend_stop=ignore} + * while setting one up goes according to vmParams, boggle me. + * According to the python agent it should be this: + * (/usr/lib64/python2.4/site-packages/agent/lib/xenxm.py) + * VM_PARAMS = { + # option: setter + 'cpu_cap': set_cpu_cap, + 'cpus': set_cpus, + 'cpu_weight': set_cpu_weight, + 'disk_other_config': set_disk_other_config, + 'disk': set_disk, + 'maxmem': set_maxmem, + 'memory': set_memory, + 'name': set_name, + 'vcpus': set_vcpus, + 'vif_other_config': set_vif_other_config, + 'vif': set_vif + } + * or: + * (/usr/lib64/python2.4/site-packages/agent/lib/xenvm.py) + VM_CFG = { + # option: checker, + 'access_control': check_list, + 'acpi': check_int, + 'apic': check_int, + 'blkif': check_int, + 'bootargs': check_str, + 'bootloader': check_str, + 'boot': check_str, + 'builder': check_str, + 'console_autoconnect': check_int, + 'cpu_cap': check_int, + 'cpuid_check': check_list, + 'cpuid': check_list, + 'cpus': check_str_or_list, + 'cpu': check_int, + 'cpu_weight': check_int, + 'device_model': check_str, + 'dhcp': check_str, + 'disk_other_config': check_list, + 'disk': check_list, + 'display': check_int, + 'expose_host_uuid': check_int, + 'extra': check_str, + 'fda': check_str, + 'fdb': check_str, + 'features': check_str, + 'gateway': check_str, + 'guest_os_type': check_str, + 'hap': check_int, + 'hostname': check_str, + 'hpet': check_int, + 'interface': check_str, + 'ioports': check_list, + 'ip': check_str, + 'irq': check_list, + 'isa': check_int, + 'kernel': check_str, + 'keymap': check_str, + 'loader': check_str, + 'localtime': check_int, + 'machine_address_size': check_int, + 'maxmem': check_int, + 'maxvcpus': check_int, + 'memory': check_int, + 'monitor_path': check_str, + 'monitor': check_int, + 'name': check_str, + 'netif': check_int, + 'netmask': check_str, + 'nfs_root': check_str, + 'nfs_server': check_str, + 'nographic': check_int, + 'nomigrate': check_int, + 'on_crash': check_str, + 'on_poweroff': check_str, + 'on_reboot': check_str, + 'on_xend_start': check_str, + 'on_xend_stop': check_str, + 'opengl': check_int, + 'pae': check_int, + 'pasued': check_int, + 'pci_msitranslate': check_int, + 'pci_power_mgmt': check_int, + 'pci': check_list, + 'ramdisk': check_str, + 'root': check_str, + 'rtc_timeoffset': check_int, + 's3_integrity': check_int, + 'sdl': check_int, + 'serial': check_str, + 'shadow_memory': check_int, + 'soundhw': check_str, + 'stdvga': check_int, + 'superpages': check_int, + 'suppress_spurious_page_faults': check_int, + 'target': check_int, + 'timer_mode': check_int, + 'tpmif': check_int, + 'tsc_mode': check_int, + 'usbdevice': check_str, + 'usb': check_int, + 'uuid': check_str, + 'vcpus': check_int, + 'vfb': check_list, + 'vhpt': check_int, + 'videoram': check_int, + 'vif2': check_list, + 'vif_other_config': check_list, + 'vif': check_list, + 'viridian': check_int, + 'vncconsole': check_int, + 'vncdisplay': check_int, + 'vnclisten': check_str, + 'vncpasswd': check_str, + 'vncunused': check_int, + 'vnc': check_int, + 'vpt_align': check_int, + 'vscsi': check_list, + 'vtpm': check_list, + 'xauthority': check_str, + 'xen_platform_pci': check_int, + } + */ + public class Vm { + /* vm attributes */ + public ArrayList<String> _vmVnc = new ArrayList<String>(); + public Map<String, String> vmVnc = new HashMap<String, String>() { + { + put(new String("type"), "vnc"); + put(new String("vncunused"), "1"); + put(new String("vnclisten"), "127.0.0.1"); + put(new String("keymap"), "en-us"); + } + }; + /* + * 'vfb': [ 'type=vnc,vncunused=1,vnclisten=127.0.0.1,keymap=en-us'] + */ + public List<String> _vmDisks = new ArrayList<String>(); + public Map<String, String> vmDisk = new HashMap<String, String>() { + { + put(new String("id"), ""); + put(new String("uuid"), ""); + put(new String("dev"), ""); + put(new String("bootable"), "1"); + put(new String("mode"), "w"); + put(new String("VDI"), ""); + put(new String("backend"), "0"); + put(new String("protocol"), "x86_32-abi"); + put(new String("uname"), ""); + } + }; + /* + * 'disk': [ + * 'file:/OVS/Repositories/0004fb0000030000aeaca859e4a8f8c0/VirtualDisks/0004fb0000120000c444117fd87ea251.img,xvda,w'] + */ + String[] _xvmVifs = new String[6]; + public ArrayList<String> _vmVifs = new ArrayList<String>(); + public Map<String, String> vmVifs = new HashMap<String, String>() { + { + put(new String("id"), ""); + put(new String("dev"), ""); + put(new String("mac"), ""); + put(new String("rate"), ""); + } + }; + /* + * 'vif': [ 'mac=00:21:f6:00:00:00,bridge=c0a80100'] + */ + + public String vmSimpleName = ""; /* human readable name */ + public String vmName = ""; /* usually vm uuid */ + public 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 ?) + */ + public String vmPrimaryPoolUuid = ""; + public String vmOnReboot = "restart"; + /* + * default weight, weight is relative to + * all VMs + */ + public int vmCpuWeight = 27500; + + public int vmMemory = 256; /* minimum memory allowed */ + public int vmCpuCap = 0; + public int vmMaxVcpus = 0; /* + * allows for dynamic adding of vcpus if + * higher than vcpus + */ + public int vmVcpus = 1; /* default to 1, can't be higher than maxvCpus */ + public Boolean vmHa = false; /* high available */ + public String vmDescription = ""; + public String vmOnPoweroff = "destroy"; + public String vmOnCrash = "restart"; + public String vmBootloader = "/usr/bin/pygrub"; /* if pv ? */ + public String vmBootArgs = ""; + public String vmExtra = ""; + public String vmOs = "Other Linux"; /* default to linux */ + + public String vmCpuCompatGroup = ""; + public String vmDomainType = "xen_pvm"; /* pv is default */ + public String vmState = "------"; + private int _vmDiskZero = 97; + private int _vmDisk = _vmDiskZero; + + public boolean isControlDomain() { + if (this.vmUuid + .contentEquals("00000000-0000-0000-0000-000000000000")) + return true; + return false; + } + + public boolean setPrimaryPoolUuid(String poolId) { + this.vmPrimaryPoolUuid = poolId; + return true; + } + + public String getPrimaryPoolUuid() { + return this.vmPrimaryPoolUuid; + } + + public 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", _vmVnc); + put("vcpus", vmVcpus); + put("OVM_cpu_compat_group", vmCpuCompatGroup); + put("OVM_domain_type", vmDomainType); + // put("state", vmState); + put("extra", vmExtra); + // put("builder", vmBuilder); + }; + }; + + 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 boolean setVmBootArgs(final String args) { + vmParams.put("bootargs", args); + return true; + } + + public String getVmBootArgs() { + return (String) vmParams.get("bootargs"); + } + + public Boolean setVmMaxCpus(Integer val) { + if (getVmCpus() > val) { + vmParams.put("maxvcpus", getVmCpus()); + } else { + vmParams.put("maxvcpus", val); + } + return true; + } + public Integer getVmMaxCpus() { + return (Integer) vmParams.get("maxvcpus"); + } + public Boolean setVmCpus(Integer val) { + vmParams.put("vcpus", val); + if (getVmMaxCpus() < val) { + setVmMaxCpus(val); + } + return true; + } + 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 Long.parseLong((String) vmParams.get("memory")); + } + + /* + * public Boolean setVmBuilder(String builder) { + * vmParams.put("builder", builder); + * return true; + * } + * public String getVmBuilder() { + * return (String) vmParams.get("builder"); + * } + */ + public Boolean setVmDomainType(String domtype) { + vmParams.put("OVM_domain_type", domtype); + return true; + } + + /* iiiis this a good idea ? */ + public String getVmDomainType() { + String domType = (String) vmParams.get("OVM_domain_type"); + if (domType == null) { + String builder = (String) vmParams.get("builder"); + if (builder.contains("linux")) { + domType = "xen_pvm"; + } else { + domType = "hvm"; + } + } + return domType; + } + public Boolean setVmState(String state) { + vmParams.put("state", state); + return true; + } + 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"); + } + + /* 'vfb': ['type=vnc,vncunused=1,vnclisten=127.0.0.1,keymap=en-us'] */ + /* + * 'disk': [ + * 'file:/OVS/Repositories/0004fb0000030000aeaca859e4a8f8c0/VirtualDisks/0004fb0000120000c444117fd87ea251.img,xvda,w'] + */ + /* 'vif': ['mac=00:21:f6:00:00:00,bridge=c0a80100'] */ + /* TODO: splork out VIFs this is not sane, same for VFBs and */ + public void setVmVncs(List<String> vncs) { + this._vmVnc.addAll(vncs); + } + public List<String> getVmVncs() { + return this._vmVnc; + } + 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 boolean addVif() { + ArrayList<String> vif = new ArrayList<String>(); + for (final String entry : _vmVifs.get(0).split(",")) { + final String[] parts = entry.split("="); + assert (parts.length == 2) : "Invalid entry: " + entry; + vif.add(parts[0] + "=" + parts[1]); + } + _vmVifs.add(StringUtils.join(vif, ",")); + return true; + } + + public Boolean addVif(Integer id, String bridge, String mac) { + String vif = "mac=" + mac + ",bridge=" + bridge; + _xvmVifs[id] = vif; + // _vmVifs.add("mac=" + mac + ",bridge=" + bridge); + return true; + } + + public boolean setupVifs() { + for (String vif : _xvmVifs) { + if (vif != null) + _vmVifs.add(vif); + } + return true; + } + + public Boolean removeVif(String bridge, String mac) { + // vmVfbs.remove("mac="+mac+",bridge="+bridge); + 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) throws Exception { + Boolean ret = false; + if (_vmDisk > _vmDiskZero) { + Integer oVmDisk = _vmDisk; + _vmDisk = _vmDiskZero; + ret = addDisk(image, "w"); + _vmDisk = oVmDisk; + } else { + ret = addDisk(image, "w"); + } + return ret; + } + public Boolean addDataDisk(String image) throws Exception { + /* + * w! means we're able to share the disk is that wise, should be + * an option in CS ? + */ + return addDisk(image, "w!"); + } + public Boolean addIso(String image) throws Exception { + /* should we check for .iso ? */ + return addDisk(image, "r!"); + } + public Boolean addDisk(String image, String mode) throws Exception { + String devName = null; + /* better accounting then _vmDisk += 1 */ + _vmDisk = _vmDiskZero + _vmDisks.size(); + if (getVmDomainType() != null && getVmDomainType().contains("hvm")) { + _vmDisk += 2; + devName = Character.toString((char) _vmDisk); + } else { + devName = "xvd" + Character.toString((char) _vmDisk); + } + + /* check for iso, force mode and additions */ + if (image.endsWith(".iso")) { + devName = devName + ":cdrom"; + mode = "r"; + } + return _addDisk(image, devName, mode); + } + + /* should be on device id too, or else we get random attaches... */ + public Boolean _addDisk(String image, String devName, String mode) throws Exception { + if (getVmDomainType() == null) { + throw new Exception("Unable to add disk without domain type " + + "(hvm, xen_pvm, ldoms_pvm (sparc), default)"); + } + /* TODO: needs to become "checkDisk" */ + for (String disk : _vmDisks) { + if (disk.contains(image)) { + return true; + } + } + _vmDisks.add("file:" + image + "," + devName + "," + mode); + vmParams.put("disk", _vmDisks); + /* accounting is done in addDisk */ + // _vmDisk += 1; + return true; + } + + public Boolean removeDisk(String image) throws Exception { + for (String disk : _vmDisks) { + if (disk.contains(image)) { + return _vmDisks.remove(disk); + } + } + return false; + } + + /* TODO: the conflict between getVm and getVmConfig becomes clear */ + /* FIX: me */ + public String getVmRootDiskPoolId() { + String poolId = getVmDiskPoolId(0); + this.setPrimaryPoolUuid(poolId); + return poolId; + } + + /* TODO: need to fork out vifs, disks and vnc stuff fill them nicely too */ + public String getVmDiskPoolId(int disk) { + String diskPath = ""; + diskPath = _getVmDiskDetail(disk, "uname"); + String st[] = diskPath.split(File.separator); + return st[3]; + } + + public String _getVmDiskDetail(int disk, String dest) { + // System.out.println(vmParams); + Map<String, Object[]> o = (Map<String, Object[]>) vmParams + .get("device"); + vmDisk = (Map<String, String>) o.get("vbd")[disk]; + return vmDisk.get(dest); + } + + public Boolean removeDisk(String file, String device) { + // + // get index and remove + return true; + } + + public boolean setVnc() { + ArrayList<String> vfb = new ArrayList<String>(); + for (final String key : vmVnc.keySet()) { + vfb.add(key + "=" + vmVnc.get(key)); + } + _vmVnc.add(StringUtils.join(vfb, ",")); + return true; + } + + public Boolean setVnc(String address) { + return setVnc("vnc", address, "en-us"); + } + + public Boolean setVnc(String type, String address, String map) { + /* unused off is domid + 5900, with unused=1 it will be "smart" */ + vmVnc.put("type", type); + vmVnc.put("vncunused", this.getVncUsed()); + vmVnc.put("vnclisten", address); + vmVnc.put("keymap", map); + setVnc(); + return true; + } + + 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() { + Integer port = getVncPort(); + if (port == null) { + return null; + } + return vmVnc.get("vnclisten"); + } + public Integer getVncPort() { + if (_getVnc("port") != null) { + return Integer.parseInt(_getVnc("port")); + } + String vnc = getVncLocation(); + if (vnc.contains(":")) { + final String[] res = vnc.split(":"); + vmVnc.put("vnclisten", res[0]); + vmVnc.put("port", res[1]); + return Integer.parseInt(res[1]); + } + return null; + } + + public String getVncLocation() { + return _getVnc("location"); + } + + public String _getVnc(String el) { + Map<String, Object[]> o = (Map<String, Object[]>) vmParams + .get("device"); + vmVnc = (Map<String, String>) o.get("vfb")[0]; + return vmVnc.get(el); + } + + public Boolean removeVfb(String type, String address, String map) { + // get index and remove + return true; + } + + public Object get(String key) { + return vmParams.get(key); + } + public <T> boolean set(String key, T arg) { + vmParams.put(key, arg); + return true; + } + } + + /* + * 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 ParserConfigurationException, + IOException, + Exception { + Object[] result = (Object[]) callWrapper("list_vms"); + if (result == null) { + return null; + } + + try { + vmList = new HashMap<String, Vm>(); + for (Object x : result) { + /* put the vmparams in, as x is a hashmap */ + // System.out.println(x); + Vm vm = new Vm(); + vm.setVmParams((Map<String, Object>) x); + this.vmList.put((String) vm.get("name"), vm); + + // System.out.println(vm.get("name") + " " + vm.get("maxmem")); + } + } catch (Exception e) { + System.err.println("Unable to list VMs: " + e.getMessage()); + throw new Exception("Unable to list VMs: " + e.getMessage()); + } + // System.out.println(vmList); + return this.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 ParserConfigurationException, IOException, Exception { + listVms(); + try { + Xen.Vm vm = this.vmList.get(name); + return vm; + } catch (Exception e) { + return null; + } + } + + public Map<String, Vm> getRunningVmConfigs() + throws ParserConfigurationException, IOException, Exception { + 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 XmlRpcException { + Object x = callWrapper("delete_vm", repoId, vmId); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + /* + * 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 */ + public Boolean saveVm(String repoId, String vmId) throws XmlRpcException { + Object x = callWrapper("save_vm", repoId, vmId); + // System.out.println(x); + if (x == null) + return true; + + return false; + } + + /* + * 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 XmlRpcException { + vm = (Vm) callWrapper("list_vm", repoId, vmId); + if (vm == null) + 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 + */ + public Boolean configureVm(String repoId, String vmId, + Map<String, Object> params) + throws XmlRpcException { + Object x = callWrapper("configure_vm", + repoId, + vmId, + params); + if (x == null) + return true; + + return false; + } + + public Boolean configureVm(String repoId, String vmId) + throws XmlRpcException { + return configureVm(repoId, + vmId, + this.vm.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 XmlRpcException { + Object x = callWrapper("pause_vm", repoId, vmId); + if (x == null) + return true; + + return false; + } + + /* + * 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 XmlRpcException { + 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 XmlRpcException { + 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 XmlRpcException { + Object x = callWrapper("migrate_vm", repoId, vmId, dest); + if (x == null) + return true; + + return false; + } + + public Boolean migrateVm(String repoId, String vmId, String dest, + boolean live, boolean ssl) throws XmlRpcException { + 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 XmlRpcException { + 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 XmlRpcException { + Object x = callWrapper("create_vm", repoId, vmId, vm.getVmParams()); + if (x == null) + return true; + + return false; + } + + public Boolean createVm(String repoId, String vmId, + Map<String, Object> vmParams) throws XmlRpcException { + Object x = callWrapper("create_vm", repoId, vmId, vmParams); + if (x == null) + return true; + + return false; + } + + /* + * 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 XmlRpcException { + Object x = callWrapper("start_vm", repoId, vmId); + if (x == null) + return true; + + return false; + } + + /* + * unpause_vm, <class 'agent.api.hypervisor.xenxm.Xen'> argument: self - + * default: None argument: repo_id - default: None argument: vm_id - + * default: None + */ + public Boolean unpauseVm(String repoId, String vmId) + throws XmlRpcException { + Object x = callWrapper("unpause_vm", repoId, vmId); + if (x == null) + return true; + + return false; + } + + /* + * 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 XmlRpcException { + Object x = callWrapper("reboot_vm", repoId, vmId, wait); + if (x == null) + return true; + + return false; + } + + public Boolean rebootVm(String repoId, String vmId) throws XmlRpcException { + 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 XmlRpcException, Exception { + this.vm = this.getRunningVmConfig(vmName); + if (vm == null) + return this.vm; + return getVmConfig(vm.getVmRootDiskPoolId(), vm.getVmUuid()); + } + + public Vm getVmConfig() { + return this.vm; + } + + /* + * 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 XmlRpcException { + Xen.Vm nVm = new Xen.Vm(); + Map<String, Object[]> x = (Map<String, Object[]>) callWrapper("get_vm_config", + repoId, + vmId); + if (x == null) { + 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.setVmVifs(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... */ + this.vm = nVm; + return nVm; + } + + /* + * 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 + */ +}