diff --git a/xCAT-client/pods/man1/cfghost.1.pod b/xCAT-client/pods/man1/cfghost.1.pod
new file mode 100644
index 000000000..20fc9cb81
--- /dev/null
+++ b/xCAT-client/pods/man1/cfghost.1.pod
@@ -0,0 +1,167 @@
+=head1 NAME
+
+B<cfghost> - Configure the RHEV hosts for a virtual environment.
+
+=head1 SYNOPSIS
+
+B<cfghost> I<noderange> [B<-a>]
+
+B<cfghost> I<noderange> [B<-n>]
+
+B<cfghost> I<noderange> [B<-p>]
+
+B<cfghost> I<noderange> [B<-e>]
+
+B<cfghost> I<noderange> [B<-d>]
+
+B<cfghost> I<noderange> [B<-r> B<-f>]
+
+=head1 DESCRIPTION
+
+The B<cfghost> command can be used to configure the RHEV-h host.
+
+The rhev-h host will register to the rhev-m automatically, but admin needs to 
+approve the host can be added to the 'cluster' with B<-a> flag .
+
+After registering, the network interfaces of host need to be added to the 'network' of 
+RHEV. And the power management for the host should be configured so that
+rhev-m could make proper decision when certain host encountered error.
+
+For each host, an entry should be added to the hypervisor table:
+
+The columns of hypervisor table:
+
+=over 2
+
+B<hypervisor.node> - rhev-h host name.
+
+B<hypervisor.type> - Must be set to 'rhevh'.
+
+B<hypervisor.mgr> - The rhev manager (The FQDN of rhev-m server) for the host.
+
+B<hypervisor.interface> - The configuration for the nics. Refer to B<-n>.
+
+B<hypervisor.cluster> - The cluster that the host will be added to. The 
+default is 'Default' cluster if not specified. 
+
+=back
+
+=head1 OPTIONS
+
+=over 2
+
+=item B<-a>
+Approve the host that to be added to cluster.
+
+Before approve, the status of the host must be 'pending_approval'.
+
+=item B<-n>
+Configure the network interfaces for the host.
+
+Note: This operation only can be run when host is in 'maintenance mode'. 
+Use B<-d> to switch the host to 'maintenance' mode.
+
+The interfaces which configured in hypervisor.interface will be added
+to the network of RHEV.
+
+The format of hypervisor.interface is multiple [network:interfacename:
+protocol:IP:netmask:gateway] sections separated with '|'. For example: 
+[rhevm2:eth0:static:10.1.0.236:255.255.255.0:0.0.0.0].
+
+=over 2
+
+B<network> - The logic network which has been created by 'cfgve -t nw' 
+or the default management network 'rhevm'.
+
+B<interfacename> - Physical network name: 'eth0','eth1'...
+
+B<protocol> - To identify which boot protocol to use for the interface: dhcp 
+or static.
+
+B<IP> - The IP address for the interface.
+
+B<netmask> - The network mask for the interface.
+
+B<gateway> - The gateay for the interface. This field only can be set when 
+the interface is added to 'rhevm' network. 
+
+=back
+
+=item B<-p>
+Configure the power management for the host.
+
+The power management must be configured for the rhev-h host to make the 
+rhev-m to monitor the power status of the host, so that when certain host 
+failed to function, rhev-m will fail over certain role like SPM to other active host.
+
+For rack mounted server, the bmc IP and user:password need to be set for the 
+power management (These parameters are gotten from ipmi table). rhev-m uses the 
+ipmi protocol to get the power status of the host. 
+
+=item B<-e>
+To activate the host.
+
+=item B<-d>
+To deactivate the host to maintenance mode.
+
+=item B<-r>
+To remove hosts from the rhev-m.
+
+The host should be deactivate to maintenance mode before the removing.
+
+=item B<-f>
+It can be used with B<-r> to remove the target object by force.
+
+For removing of host, if B<-f> is specified, the host will be deactivated to maintenance before the removing.
+
+=item B<-h>
+Display usage message.
+
+=back
+
+=head1 RETURN VALUE
+
+0  The command completed successfully.
+
+1  An error has occurred.
+
+=head1 EXAMPLES
+
+=over 2
+
+=item 1.
+To approve the host 'host1', enter:
+
+ cfghost host1 -a
+
+=item 2.
+To configure the network interface for the host 'host1', enter:
+
+ cfghost host1 -n
+
+=item 3.
+To configure the power management for the host 'host1', enter:
+
+ cfghost host1 -p
+
+=item 4.
+To activate the host 'host1', enter:
+
+ cfghost host1 -e
+
+=item 5.
+To deactivate the host 'host1', enter:
+
+ cfghost host1 -d
+
+=item 6.
+To remove the host 'host1', enter:
+
+ cfghost host1 -r -f
+ 
+=back
+
+=head1 FILES
+
+/opt/xcat/bin/cfghost
+
diff --git a/xCAT-client/pods/man1/cfgve.1.pod b/xCAT-client/pods/man1/cfgve.1.pod
new file mode 100644
index 000000000..5bcf43e9e
--- /dev/null
+++ b/xCAT-client/pods/man1/cfgve.1.pod
@@ -0,0 +1,186 @@
+=head1 NAME
+
+B<cfgve> - Configure the elements for a virtual environment.
+
+=head1 SYNOPSIS
+
+B<cfgve> B<-t> dc B<-m> manager B<-o> object [B<-c> | B<-r>]
+
+B<cfgve> B<-t> cl B<-m> manager B<-o> object [B<-c> | B<-r> B<-f>]
+
+B<cfgve> B<-t> sd B<-m> manager B<-o> object [B<-c> | B<-g> | B<-s> 
+| B<-a> | B<-b> | B<-r> B<-f>]
+
+B<cfgve> B<-t> nw B<-m> manager B<-o> object [B<-c> B<-d> data center 
+| B<-r>]
+
+B<cfgve> B<-t> tpl B<-m> manager B<-o> object [B<-r>]
+
+
+=head1 DESCRIPTION
+
+The B<cfgve> command can be used to configure a virtual environment for 
+'Storage Domain', 'Network' and 'Template' objects.
+
+The mandatory parameter B<-m manager> is used to specify the address of the 
+manager of virtual environment. xCAT needs it to access the RHEV manager.
+
+The mandatory parameter B<-t type> is used to specify the type of the target 
+object.
+
+Basically, B<cfgve> command supports five types of object: B<dc>, B<cl>, 
+B<sd>, B<nw> and B<tpl>. 
+
+=over 3
+
+B<dc> - The B<create> and B<remove> operations are supported.
+
+B<cl> - The B<create> and B<remove> operations are supported.
+
+B<sd>  - The B<create>, B<attach>, B<detach>, B<activate>, 
+B<deactivate> and B<remove> operations are supported.
+
+B<nw>  - The B<create> and B<remove> operations are supported.
+
+B<tpl> - The B<remove> operation is supported.
+
+=back
+
+The mandatory parameter B<-o object> is used to specify which object to configure.
+
+
+=head1 OPTIONS
+
+=over 2
+
+=item B<-t>
+Specify the B<type> of the target object.
+
+Supported types:
+ B<dc>  - Data Center
+ B<cl>  - Cluster
+ B<sd>  - Storage Domain
+ B<nw>  - Network
+ B<tpl> - Template
+
+=item B<-m>
+Specify the manager of the virtual environment. 
+
+For RHEV, the FQDN (Fully Qualified Domain Name) of the rhev manager have 
+to be specified.
+
+=item B<-o>
+The name of the target object.
+
+=item B<-d>
+The name of data center.
+
+Specify the 'Data Center' that will be used for the object to be attached to. 
+It is used by <nw> type.
+
+=item B<-c>
+To create the target object.
+
+For creating of B<Storage Domain>, the target storage domain will be created 
+first, then attached to data center and activated.
+
+The parameters that used to create the storage domain are gotten 
+from 'virtsd' table. The detail parameters in the virtsd table:
+
+=over 3
+
+B<virtsd.node> - The name of the storage domain.
+
+B<virtsd.sdtype> - The type of storage domain. Valid value: data, iso, export. 
+Default value is 'data'.
+
+B<virtsd.stype> - The storage type. "nfs" or "localfs".
+
+B<virtsd.location> - The location of the storage. 
+B<nfs>: Format: [nfsserver:nfspath]. 
+The NFS export directory must be configured for read write access and must 
+be owned by vdsm:kvm.
+B<localfs>: "/data/images/rhev" is set by default.
+
+B<virtsd.host> - A host must be specified for a storage doamin as SPM 
+(Storage Pool Manager) when initialize the storage domain. The role of SPM 
+may be migrated to other host by rhev-m during the running of the datacenter 
+(For example, when the current SPM encountered issue or going to maintenance 
+status.
+  
+B<virtsd.datacenter> - The storage will be attached to. 'Default' data center 
+is the default value. 
+
+=back
+
+=item B<-g>
+To activate the target object.
+
+=item B<-s>
+To deactivate the target object.
+
+=item B<-a>
+To attach the target object.
+
+=item B<-b>
+To detach the target object.
+
+=item B<-r>
+To remove the target object.
+
+For removing of B<Storage Domain>, the storage space will be formatted after removing.
+
+=item B<-f>
+It can be used with B<-r> to remove the target object by force.
+
+For removing of B<Storage Domain>, if B<-f> is specified, the storage domain will be deactivated and detached from data center before the removing.
+
+=item B<-h>
+Display usage message.
+
+=back
+
+=head1 RETURN VALUE
+
+0  The command completed successfully.
+
+1  An error has occurred.
+
+=head1 EXAMPLES
+
+=over 2
+
+=item 1.
+To create the Storage Domain 'sd1', enter:
+
+ cfgve -t sd -m <FQDN of rhev manager> -o sd1 -c
+
+=item 2.
+To deactivate the Storage Domain 'sd1' from data center, enter:
+
+ cfgve -t sd -m <FQDN of rhev manager> -o sd1 -s
+
+=item 3.
+To remove the Storage Domain 'sd1', enter:
+
+ cfgve -t sd -m <FQDN of rhev manager> -o sd1 -r
+
+=item 4.
+To create the network 'nw1', enter:
+
+ cfgve -t nw -m <FQDN of rhev manager> -o nw1 -c
+
+=item 5.
+To remove the template 'tpl01', enter:
+
+ cfgve -t tpl -m <FQDN of rhev manager> -o tpl01 -r
+
+=back
+
+=head1 FILES
+
+/opt/xcat/bin/cfgve
+
+=head1 SEE ALSO
+
+L<lsve(1)|lsve.1>
diff --git a/xCAT-client/pods/man1/lsve.1.pod b/xCAT-client/pods/man1/lsve.1.pod
new file mode 100644
index 000000000..699fc8380
--- /dev/null
+++ b/xCAT-client/pods/man1/lsve.1.pod
@@ -0,0 +1,181 @@
+=head1 NAME
+
+B<lsve> - Lists detail attributes for a virtual environment.
+
+=head1 SYNOPSIS
+
+B<lsve> [B<-t> type] [B<-m> manager] [B<-o> object]
+
+=head1 DESCRIPTION
+
+The B<lsve> command can be used to list a virtual environment for 
+'Data Center', 'Cluster', 'Storage Domain', 'Network' and 'Template' objects.
+
+The mandatory parameter B<-m manager> is used to specify the address of the 
+manager of virtual environment. xCAT needs it to access the RHEV manager.
+
+The mandatory parameter B<-t type> is used to specify the type of the target 
+object.
+
+Basically, B<lsve> command supports three types of object: B<dc>, B<cl>, B<sd>, B<nw> 
+and B<tpl>. 
+
+The mandatory parameter B<-o object> is used to specify which object to list.
+
+=head1 OPTIONS
+
+=over 2
+
+=item B<-t>
+Specify the B<type> of the target object.
+
+Supported types:
+ B<dc>  - Data Center (For type of 'dc', all the elements belongs to the data 
+   center will be listed.)
+ B<cl>  - Cluster
+ B<sd>  - Storage Domain
+ B<nw>  - Network
+ B<tpl> - Template
+
+=item B<-m>
+Specify the manager of the virtual environment. 
+
+For RHEV, the FQDN (Fully Qualified Domain Name) of the rhev manager have to be specified.
+
+=item B<-o>
+The target object to display.
+
+=item B<-h>
+Display usage message.
+
+=back
+
+=head1 RETURN VALUE
+
+0  The command completed successfully.
+
+1  An error has occurred.
+
+=head1 EXAMPLES
+
+=over 2
+
+=item 1.
+To list the data center 'Default', enter:
+
+ lsve -t B<dc> -m <FQDN of rhev manager> -o Default
+
+Output is similar to:
+
+  datacenters: [Default]
+  description: The default Data Center
+  state: up
+  storageformat: v1
+  storagetype: nfs
+    clusters: [Default]
+      cpu: Intel Westmere Family
+      description: The default server cluster
+      memory_hugepage: true
+      memory_overcommit: 100
+    storagedomains: [image]
+      available: 55834574848
+      committed: 13958643712
+      ismaster: true
+      status: active
+      storage_add: <Address of storage domain>
+      storage_format: v1
+      storage_path: /vfsimg
+      storage_type: nfs
+      type: data
+      used: 9663676416
+    networks: [rhevm2]
+      description:
+      state: operational
+      stp: false
+    networks: [rhevm]
+      description: Management Network
+      state: operational
+      stp: false
+    templates: [Blank]
+      bootorder: hd
+      cpucore: 1
+      cpusocket: 1
+      creation_time: 2008-04-01T00:00:00.000-04:00
+      display: spice
+      memory: 536870912
+      state: ok
+      stateless: false
+      type: desktop
+
+
+=item 2.
+To list the cluster 'Default', enter:
+
+ lsve -t B<cl> -m <FQDN of rhev manager> -o Default
+
+Output is similar to:
+
+  cpu: Intel Westmere Family
+  description: The default server cluster
+  memory_hugepage: true
+  memory_overcommit: 10
+
+
+=item 3.
+To list the Storage Domain 'image', enter:
+
+ lsve -t B<sd> -m <FQDN of rhev manager> -o image
+
+Output is similar to:
+  storagedomains: [image]
+    available: 55834574848
+    committed: 13958643712
+    ismaster: true
+    status:
+    storage_add: <Address of storage domain>
+    storage_format: v1
+    storage_path: /vfsimg
+    storage_type: nfs
+    type: data
+    used: 9663676416
+
+=item 4.
+To list the network 'rhevm', enter:
+
+ lsve -t B<nw> -m <FQDN of rhev manager> -o rhevm
+
+Output is similar to:
+
+  networks: [rhevm]
+    description: Management Network
+    state: operational
+    stp: false
+
+=item 5.
+To list the template 'tpl01', enter:
+
+ lsve -t tpl -m <FQDN of rhev manager> -o tpl01
+
+Output is similar to:
+
+  templates: [tpl01]
+    bootorder: network
+    cpucore: 2
+    cpusocket: 2
+    creation_time: 2012-08-22T23:52:35.953-04:00
+    display: vnc
+    memory: 1999634432
+    state: ok
+    stateless: false
+    type: server
+
+
+=back
+
+=head1 FILES
+
+/opt/xcat/bin/lsve
+
+=head1 SEE ALSO
+
+L<cfgve(1)|cfgve.1>
\ No newline at end of file
diff --git a/xCAT-server/lib/xcat/plugins/rhevm.pm b/xCAT-server/lib/xcat/plugins/rhevm.pm
new file mode 100644
index 000000000..1a9b03132
--- /dev/null
+++ b/xCAT-server/lib/xcat/plugins/rhevm.pm
@@ -0,0 +1,3750 @@
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+# This module is used to support the rhev
+# The rhev-m is used as the agent to manage the storage domain, network, rhev-h
+# There are concepts Datacenter and Cluster for the rhev, SD and network belongs to DC, 
+#   rhev-h (host) belongs to cluster
+#
+# When installing rhev-h, it will try to register to rhev-m. From xCAT point of view, just approve.
+# The fence must be configured for the rhev-h to enable the SD management, otherwise when
+#    when the SPM failed, the failure take over for the SPM cannot happen automatically.
+#
+# The SD needs to be created with a host as the SPM (Storage Pool Manager), when the current
+#   SPM failed, SPM will switch to another available rhev-h.
+#
+# Add rhevh to the management 
+#   for the rhevh, the adding should be done automatically that specify the rhev-m infor when installing of the rhev-h
+# Need to run the approval for the host to be added to the rhevm
+#
+# The features that are not used
+    # tag, to catalog the resources with tag
+    # role, for access permission
+    # domain, for user/group management
+#TODO: handle the functions base on the version
+#TODO: handle the datacenter and cluster management
+#TODO: add the support of iscsi storage domain
+
+
+
+package xCAT_plugin::rhevm;
+
+use strict;
+use warnings;
+
+use POSIX qw(WNOHANG nice);
+use POSIX qw(WNOHANG setsid :errno_h);
+use IO::Select;
+require IO::Socket::SSL; IO::Socket::SSL->import('inet4');
+use Time::HiRes qw(gettimeofday sleep);
+
+use Fcntl qw/:DEFAULT :flock/;
+use File::Path;
+use File::Copy;
+
+use Getopt::Long;
+Getopt::Long::Configure("bundling");
+Getopt::Long::Configure("pass_through");
+
+use HTTP::Headers;
+use HTTP::Request;
+use XML::LibXML;
+
+use xCAT::Table;
+use xCAT::MsgUtils;
+use xCAT::Usage;
+
+sub handled_commands{
+    return {
+        copycd => 'rhevm',
+        mkinstall => "nodetype:os=(rhevh.*)",
+        rpower => 'nodehm:power,mgt',
+        rsetboot => 'nodehm:power,mgt',
+        rmigrate => 'nodehm:power,mgt',
+        addhost => 'hypervisor:type=(rhelh)',
+        cfghost => 'hypervisor:type=(rhevh)',
+        cfgve => 'rhevm',
+        lsve => 'rhevm',
+        lsvm => ['hypervisor:type=(rhev.*)','nodehm:mgt'],
+        mkvm => 'nodehm:mgt',
+        rmvm => 'nodehm:mgt',
+        clonevm => 'nodehm:mgt',
+        rmigrate => 'nodehm:mgt',
+        #rinv => 'nodehm:mgt',
+        chvm => 'nodehm:mgt',
+        #rshutdown => "nodetype:os=(rhev.*)",
+        #rmhypervisor => ['hypervisor:type','nodetype:os=(rhev.*)'],
+        #chhypervisor => ['hypervisor:type','nodetype:os=(rhev.*)'],
+        rhevhupdateflag => "nodetype:os=(rhevh.*)",
+        getrvidparms => 'nodehm:mgt',
+    };
+}
+
+my $verbose;
+my $global_callback;
+
+sub preprocess_request {
+    my $request = shift;
+    my $callback = shift;
+    
+    #if already preprocessed, go straight to request
+    if ((defined($request->{_xcatpreprocessed}->[0]))
+        && ($request->{_xcatpreprocessed}->[0] == 1)) {
+        return [$request];
+    }
+
+    unless ($request and $request->{command} and $request->{command}->[0]) { return; }
+    if ($request->{command}->[0] eq 'copycd') {
+    	  return [$request];
+    }
+
+    my $nodes = $request->{node};
+    my $command = $request->{command}->[0];
+    my $extraargs = $request->{arg};
+
+    if ($extraargs) {
+        @ARGV=@{$extraargs};
+        my $help;
+        GetOptions("V" => \$verbose, 'h|help' => \$help); 
+        $global_callback = $callback;
+        if ($help) {
+            my $usage_string = xCAT::Usage->getUsage($command);
+            my $rsp;
+            push @{$rsp->{data}}, $usage_string;
+            xCAT::MsgUtils->message("I", $rsp, $callback);
+            return ();
+        }
+    }
+
+    # Read the user password for the rhevm
+    # Only support the general password in passwd table
+    my $passtab = xCAT::Table->new('passwd');
+    my ($rhevmadminpw,$rhevhrootpw, $rhevhadminpw);
+    if ($passtab) {
+        my $pw = $passtab->getAttribs({'key'=>'rhevm', 'username'=>'admin'}, 'password');
+        if (defined($pw)) {
+            $rhevmadminpw = $pw->{password};
+        }
+        # The $rhevmadminpw must be unencrypted, since http need this to generate the authorized key
+        if (!$rhevmadminpw) {
+            my $rsp;
+            push @{$rsp->{data}}, "The unencrypted password of \'admin\' for the rhevm much be set in the passwd table.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return ();
+        } 
+
+        $pw = $passtab->getAttribs({'key'=>'rhevh', 'username'=>'admin'}, 'password');
+        if (defined($pw)) {
+            $rhevhadminpw = $pw->{password};
+        }
+        if (!$rhevhadminpw) {
+            my $rsp;
+            push @{$rsp->{data}}, "The password of \'admin\' for the rhevh much be set in the passwd table.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return ();
+        } else {
+            $rhevhadminpw =  authpw($rhevhadminpw);
+        }
+        
+        $pw = $passtab->getAttribs({'key'=>'rhevh', 'username'=>'root'}, 'password');
+        if (defined($pw)) {
+            $rhevhrootpw = $pw->{password};
+            if ($rhevhrootpw) {
+                $rhevhrootpw = authpw($rhevhrootpw);
+            }
+        }
+    }
+
+    # Get the host for the nodes
+    my $vmtab = xCAT::Table->new("vm");
+    my $vmtabhash = $vmtab->getNodesAttribs($nodes,['host','mgr']);
+    my $hyptab = xCAT::Table->new("hypervisor");
+    my $hyptabhash = $hyptab->getNodesAttribs($nodes,['type','mgr']);
+
+    # The hash that use hyp as key
+    # In following example: rhevm1 is rhev-m;  rhevh1 and rhevh2 are rhev-h
+    # vm11 is vm which located at rhevh1, vm12 is vm which located at rhevh2
+    # vm1 has not specific host to bind
+    # The user and password for rhev-m and rhev-h also specified
+    #  |0  'rhevm1'
+    #  |1  HASH(0x99066e0)
+    #  |   'host' => HASH(0x9906230)
+    #  |      'rhevh1' => HASH(0x99064a0)
+    #  |         'adminpw' => '$1$k343MVXm$tZrjCk5GUJgRguNxdyIrT0'
+    #  |         'node' => ARRAY(0x98f91a8)
+    #  |            0  'vm11'
+    #  |         'rootpw' => '$1$k3Yvim3b$9NLOSVlIiQY3ZYluT.CqP/'
+    #  |      'rhevh2' => HASH(0x99064e8)
+    #  |         'adminpw' => '$1$k343MVXm$tZrjCk5GUJgRguNxdyIrT0'
+    #  |         'node' => ARRAY(0x9905c60)
+    #  |            0  'vm12'
+    #  |         'rootpw' => '$1$k3Yvim3b$9NLOSVlIiQY3ZYluT.CqP/'
+    #  |   'node' => ARRAY(0x98ff378)
+    #  |      0  'vm1'
+    #  |   'pw' => '$1$9IXfmatc$Vcoy23AF5q0BcBE0cB3Uq/'
+    #  |   'user' => 'admin'
+    my %rhevm_hash;
+
+    foreach my $node (@$nodes){
+        my $vment = $vmtabhash->{$node}->[0];
+        my $hypent = $hyptabhash->{$node}->[0];
+        if (defined($vment->{'mgr'})) {    # is a vm and has rhevm info
+            $rhevm_hash{$vment->{'mgr'}}->{'user'} = "admin";
+            $rhevm_hash{$vment->{'mgr'}}->{'pw'} = $rhevmadminpw;
+            if (defined($vment->{'host'})) {    # is a vm and has rhevm, host info
+                push @{$rhevm_hash{$vment->{'mgr'}}->{'host'}->{$vment->{'host'}}->{'node'}}, $node;
+                $rhevm_hash{$vment->{'mgr'}}->{'host'}->{$vment->{'host'}}->{'adminpw'} = $rhevhadminpw;
+                $rhevm_hash{$vment->{'mgr'}}->{'host'}->{$vment->{'host'}}->{'rootpw'} = $rhevhrootpw;
+            } else {
+                push @{$rhevm_hash{$vment->{'mgr'}}->{'node'}}, $node;
+            }
+        } elsif (defined($hypent->{'mgr'})) {    # is a rhevh
+            $rhevm_hash{$hypent->{'mgr'}}->{'user'} = "admin";
+            $rhevm_hash{$hypent->{'mgr'}}->{'pw'} = $rhevmadminpw;
+            push @{$rhevm_hash{$hypent->{'mgr'}}->{'host'}->{$node}->{'node'}}, $node;
+            $rhevm_hash{$hypent->{'mgr'}}->{'host'}->{$node}->{'adminpw'} = $rhevhadminpw;
+            $rhevm_hash{$hypent->{'mgr'}}->{'host'}->{$node}->{'rootpw'} = $rhevhrootpw;
+        } elsif ($command eq 'lsvm') {    # hope the node is a rhevm, that only the lsvm can be run to display
+        } else {
+            my $rsp;
+            push @{$rsp->{data}}, "$node: Missing the management point in \'vm.mgr\' or \'hypervisor.mgr\'.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+        }
+    }
+
+    # For the lsve or cfgve command, get the object from argument
+    if ($command =~ /^(cfgve|lsve)$/) {
+        # -t type -o obj -m mgr 
+        my $mgr;
+        unless ($extraargs) {
+            return ();
+        }
+        @ARGV=@{$extraargs};
+        GetOptions("m=s" => \$mgr); #use mgr to know where to dispatch this request
+        if ($mgr) {
+            $rhevm_hash{$mgr}->{'user'} = "admin";
+            $rhevm_hash{$mgr}->{'pw'} = $rhevmadminpw;
+        } else {
+            my $rsp;
+            push @{$rsp->{data}}, "The flag -m is necessary to perform the command.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return ();
+        }
+    }
+
+    # Prepare the request for each service node
+    # The dispatch depends on the rhevm. Since the operation is in serial, so no need to use the service node.
+    my @requests;
+    my @rhevms=keys(%rhevm_hash);
+    my $sn = xCAT::Utils->get_ServiceNode(\@rhevms, 'xcat', "MN");
+    foreach my $snkey (keys %$sn){
+        my $reqcopy = {%$request};
+        $reqcopy->{'_xcatdest'} = $snkey;
+        $reqcopy->{_xcatpreprocessed}->[0] = 1;
+        # Search the node base on the hypervisor
+        my $rhevms=$sn->{$snkey};
+        my @moreinfo=();
+        my @nodes=();
+        foreach my $rhevm (@$rhevms) {
+            #[rhevm][user_rhevm][pw_rhevm][rhevh][user_rhevh][pw_rhevh][nodes]
+            my $data_rhevm = "[$rhevm][$rhevm_hash{$rhevm}->{'user'}][$rhevm_hash{$rhevm}->{'pw'}]";
+            if (defined ($rhevm_hash{$rhevm}->{'host'})) {
+                foreach my $host (keys %{$rhevm_hash{$rhevm}->{'host'}}) {
+                    my $data_rhevh = $data_rhevm."[$host][$rhevm_hash{$rhevm}->{'host'}->{$host}->{'adminpw'}][$rhevm_hash{$rhevm}->{'host'}->{$host}->{'rootpw'}][".join(',',@{$rhevm_hash{$rhevm}->{'host'}->{$host}->{'node'}})."]";
+                    push @moreinfo, $data_rhevh;
+                    push @nodes, @{$rhevm_hash{$rhevm}->{'host'}->{$host}->{'node'}};
+                }
+            }
+            if (defined  ($rhevm_hash{$rhevm}->{'node'})) {
+                my $data_node = $data_rhevm."[][][][".join(',',@{$rhevm_hash{$rhevm}->{'node'}})."]";
+                push @moreinfo, $data_node;
+                push @nodes, @{$rhevm_hash{$rhevm}->{'node'}};
+            }
+            unless (defined ($rhevm_hash{$rhevm}->{'host'}) || defined  ($rhevm_hash{$rhevm}->{'node'})) {
+                push @moreinfo, $data_rhevm."[][][][]";
+            }
+        }
+        if (scalar @nodes) {
+            $reqcopy->{node} = \@nodes;
+        }
+        $reqcopy->{moreinfo}=\@moreinfo;
+        if ($verbose) {
+            $reqcopy->{verbose} = 1;
+        }
+        push @requests, $reqcopy;
+    }
+
+    return \@requests;
+}
+
+
+sub process_request {
+    my $request = shift;
+    my $callback = shift;
+    my $subreq = shift;
+
+    my $command = $request->{command}->[0];
+    my $args = $request->{arg};
+    my $nodes = $request->{node};
+
+    $verbose = $request->{verbose};
+    
+    if($command eq 'copycd'){
+        return copycd($request,$callback);
+    }  elsif ($command eq 'rhevhupdateflag') {
+        # handle the command to update bootloader configuration file for rhevh installation
+        return rhevhupdateflag($request,$callback,$subreq);
+    }
+
+    my $moreinfo;
+    if ($request->{moreinfo}) { 
+        $moreinfo=$request->{moreinfo}; 
+    } else {
+        my $rsp;
+        push @{$rsp->{data}}, "";
+        xCAT::MsgUtils->message("I", $rsp, $callback);
+    }
+
+    my %rhevm_hash;
+    foreach my $info (@$moreinfo) {
+        $info=~/^\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
+        my $rhevm=$1;
+        my $rhevmuser = $2;
+        my $rhevmpw = $3;
+        my $rhevh=$4;
+        my $rhevhadminpw = $5;
+        my $rhevhrootpw = $6;
+        my @nodes;
+        if ($7) { @nodes =split(',', $7) };
+
+        $rhevm_hash{$rhevm}->{name} = $rhevm;
+        $rhevm_hash{$rhevm}->{user} = $rhevmuser;
+        $rhevm_hash{$rhevm}->{pw} = $rhevmpw;
+        if ($rhevh) {
+            $rhevm_hash{$rhevm}->{host}->{$rhevh}->{name} = $rhevh;
+            $rhevm_hash{$rhevm}->{host}->{$rhevh}->{adminpw} = $rhevhadminpw;
+            $rhevm_hash{$rhevm}->{host}->{$rhevh}->{rootpw} = $rhevhrootpw;
+            push @{$rhevm_hash{$rhevm}->{host}->{$rhevh}->{node}}, @nodes;
+        } elsif (@nodes) {
+            push @{$rhevm_hash{$rhevm}->{node}}, @nodes;
+        }
+    }
+
+    # TODO: Plan to make long http connection to the every rhevm, but it does not work well
+    foreach my $rhevm (keys %rhevm_hash) {
+        # TODO fork process for each rhev-m
+        # get the ca.crt for the specific rhevm
+        if (! -r "/etc/xcat/rhevm/$rhevm/ca.crt") {
+            if (! -d "/etc/xcat/rhevm/$rhevm") {
+                mkpath ("/etc/xcat/rhevm/$rhevm");
+            }
+            my $cmd = "cd /etc/xcat/rhevm/$rhevm/; wget -q http://$rhevm:8080/ca.crt";
+            xCAT::Utils->runcmd($cmd, -1);
+            if ($::RUNCMD_RC != 0) {
+                my $rsp;
+                push @{$rsp->{data}}, "Could not get the CA certificate from http://$rhevm:8080/ca.crt.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                return undef;
+            }
+        }
+   }
+
+    if($command eq 'mkinstall'){
+        mkinstall($request, $callback, \%rhevm_hash);
+    } elsif ($command eq "rsetboot") {
+        rsetboot($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "addhost") {
+        addhost($callback, \%rhevm_hash);
+    } elsif ($command eq "cfghost") {
+        cfghost($callback, \%rhevm_hash, $nodes, $args);
+    } elsif ($command eq "cfgve") {
+        cfgve($callback, \%rhevm_hash,$args);
+    } elsif ($command eq "lsve") {
+        lsve($callback, \%rhevm_hash,$args);
+    } elsif ($command eq "rmhost") {
+        rmhost();
+    } elsif ($command eq "lsvm") {
+        lsvm($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "chvm") {
+        chvm($callback, \%rhevm_hash, $nodes, $args);
+    }elsif ($command eq "mkvm") {
+        mkvm($callback, \%rhevm_hash, $nodes, $args);
+    } elsif ($command eq "rmvm") {
+        rmvm($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "clonevm") {
+        clonevm($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "rmigrate") {
+        rmigrate($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "rpower") {
+        power ($callback, \%rhevm_hash, $args);
+    } elsif ($command eq "getrvidparms") {
+        getrvidparms ($callback, \%rhevm_hash, $nodes);
+    }
+
+}
+
+my @cpiopid;
+
+# Perform the copycds for rhev-h to a specific dirtory 
+sub copycd {
+    my $request = shift;
+    my $callback = shift;
+
+    my $distname;
+    my $arch;
+    my $path;
+    my $mntpath;
+    my $file;  # the iso source file must be passed to generate the initrd
+
+    @ARGV = @{$request->{arg}};
+    GetOptions( 'n=s' => \$distname,
+                'a=s' => \$arch,
+                'p=s' => \$path,
+                'm=s' => \$mntpath,
+                'f=s' => \$file,
+              );
+
+    unless ($distname && $arch && $mntpath) {
+        return;
+    }
+
+    if ($distname && $distname !~ /^rhev/) {
+        return;
+    } elsif (! $file) {
+        $callback->({error => "Only support to use the iso file for rhev"});
+        return;
+    }
+
+    my $installroot = "/install";
+    my @entries =  xCAT::Utils->get_site_attribute("installdir");
+    my $t_entry = $entries[0];
+    if ( defined($t_entry) ) {
+        $installroot = $t_entry;
+    }
+    my $rsp;
+    push @{$rsp->{data}}, "Copying media to $installroot/$distname/$arch/";
+    xCAT::MsgUtils->message("I", $rsp, $callback);
+
+    unless ($path) {
+        $path = "$installroot/$distname/$arch";
+    }
+    my $omask = umask 0022;
+    if(-l $path)
+    {
+        unlink($path);
+    }
+    mkpath("$path");
+    umask $omask;
+
+    my $rc;
+    my $reaped = 0;
+    $SIG{INT} = $SIG{TERM} = sub {
+        foreach(@cpiopid){
+            kill 2, $_;
+        }
+        if ($::CDMOUNTPATH) {
+            chdir("/");
+            system("umount $::CDMOUNTPATH");
+        }
+    };
+    my $KID;
+    chdir $mntpath;
+    my $numFiles = `find . -print | wc -l`;
+    my $child = open($KID, "|-");
+    unless (defined $child)
+    {
+        $callback->({error => "Media copy operation fork failure"});
+        return;
+    }
+    if ($child)
+    {
+        push @cpiopid, $child;
+        my @finddata = `find .`;
+        for (@finddata)
+        {
+            print $KID $_;
+        }
+        close($KID);
+        $rc = $?;
+    }
+    else
+    {
+        nice 10;
+        my $c = "nice -n 20 cpio -vdump $path";
+        my $k2 = open(PIPE, "$c 2>&1 |") ||
+           $callback->({error => "Media copy operation fork failure"});
+        push @cpiopid, $k2;
+        my $copied = 0;
+        my ($percent, $fout);
+        while(<PIPE>){
+          next if /^cpio:/;
+          $percent = $copied / $numFiles;
+          $fout = sprintf "%0.2f%%", $percent * 100;
+          $callback->({sinfo => "$fout"});
+          ++$copied;
+        }
+        exit;
+    }
+
+    # copy the iso to the source dir to generate the initrd by nodeset
+    copy ($file, "$installroot/$distname/$arch/rhevh.iso");
+}
+
+# Perform the install preparation for the installation of rhev-h
+sub mkinstall {
+    my $request  = shift;
+    my $callback = shift;
+    my $rhevm_hash    = shift;
+    my @nodes    = @{$request->{node}};
+
+    my %doneimgs;
+
+    my $installdir = "/install";
+    my @ents = xCAT::Utils->get_site_attribute("installdir");
+    my $site_ent = $ents[0];
+    if( defined($site_ent) )
+    {
+        $installdir = $site_ent;
+    }
+
+    my $tftpdir = "/tftpboot";
+    @ents = xCAT::Utils->get_site_attribute("tftpdir");
+    $site_ent = $ents[0];
+    if( defined($site_ent) )
+    {
+        $tftpdir = $site_ent;
+    }
+
+    my $nttab = xCAT::Table->new('nodetype');
+    my %ntents = %{$nttab->getNodesAttribs(\@nodes, ['profile', 'os', 'arch', 'provmethod'])};
+
+    my $bptab  = xCAT::Table->new('bootparams',-create=>1);
+    my $restab = xCAT::Table->new('noderes',-create=>1);
+    my %resents = %{$restab->getNodesAttribs(\@nodes, ['xcatmaster', 'tftpdir', 'primarynic', 'installnic'])};
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $node (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if ($node eq $rhevm_hash->{$rhevm}->{host}->{$node}->{node}->[0]) {  #this is a rhev-h
+                    my $ent = $ntents{$node}->[0];
+                    my $os = $ent->{os};
+                    my $arch    = $ent->{arch};
+                    my $profile = $ent->{profile};
+            
+                    my ($kcmdline,$k,$i);
+                    if ($arch =~ /x86/
+                        && -r "$installdir/$os/$arch/isolinux/vmlinuz0"
+                        && -r "$installdir/$os/$arch/isolinux/initrd0.img"
+                        && -r "$installdir/$os/$arch/rhevh.iso") {
+                        my $tftppath = "$tftpdir/xcat/$os/$arch";
+                        mkpath($tftppath);
+                        copy ("$installdir/$os/$arch/isolinux/vmlinuz0", $tftppath);
+            
+                        # append the full iso to the initrd. It will be downloaded to the node and as the installation source to install rhev-h
+                        unless ($doneimgs{"$os|$arch"}) {
+                            my $cmd = "cd $installdir/$os/$arch/; echo rhevh.iso | cpio -H newc --quiet -L -o | gzip -9 | cat $installdir/$os/$arch/isolinux/initrd0.img - > $tftppath/initrd0.img";
+                            `$cmd`;
+                            $doneimgs{"$os|$arch"} = 1;
+                        }
+                        $k = "xcat/$os/$arch/vmlinuz0";
+                        $i = "xcat/$os/$arch/initrd0.img";
+                    } else {
+                        my $rsp;
+                        push @{$rsp->{data}}, "Cannot find vmlinux";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    }
+            
+                    $kcmdline = " rootflags=loop";
+                    $kcmdline .= " root=live:/rhevh.iso";
+                    $kcmdline .= " rootfstype=auto ro liveimg nomodeset check rootflags=ro crashkernel=512M-2G:64M,2G-:128M elevator=deadline processor.max_cstate=1 install reinstall quiet rd_NO_LVM rhgb rd_NO_LUKS rd_NO_MD rd_NO_DM";
+
+                    # set the boot device
+                    my $ksdev = "";
+                    $ent = $resents{$node}->[0];
+                    if ($ent->{installnic}) {
+                        if ($ent->{installnic} eq "mac") {
+                            my $mactab = xCAT::Table->new("mac");
+                            my $macref = $mactab->getNodeAttribs($node, ['mac']);
+                            $ksdev = $macref->{mac};
+                        }  else {
+                            $ksdev = $ent->{installnic};
+                        }
+                     } elsif ($ent->{primarynic}) {
+                        if ($ent->{primarynic} eq "mac") {
+                            my $mactab = xCAT::Table->new("mac");
+                            my $macref = $mactab->getNodeAttribs($node, ['mac']);
+                            $ksdev = $macref->{mac};
+                        } else {
+                            $ksdev = $ent->{primarynic};
+                        }
+                    } else {
+                        my $rsp;
+                        push @{$rsp->{data}}, "No network interface was set: installnic, primarynic";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    }
+                    
+                    # set the storage parameters
+                    $kcmdline .= " storage_init";
+                    
+                    # set the bootif
+                    $kcmdline .= " BOOTIF=$ksdev ip=dhcp";
+            
+                    # set the passwd for admin and root
+                    $kcmdline .=  " adminpw=$rhevm_hash->{$rhevm}->{host}->{$node}->{adminpw} rootpw=$rhevm_hash->{$rhevm}->{host}->{$node}->{rootpw} ssh_pwauth=1";
+            
+                    # set the hostname and password of the management server for the node so that node could register to the rhevm automatically.
+                    $kcmdline .= " management_server=$rhevm_hash->{$rhevm}->{name} rhevm_admin_password=";
+                    $kcmdline .= authpw($rhevm_hash->{$rhevm}->{pw});
+            
+                    # set the flag update trigger, after installing of rhev-h, this url will be 'wget', xCAT MN will handle this event to run the upfateflag for this rhev-h
+                    my $xcatmaster;
+                    if ($ent and $ent->{xcatmaster}) {
+                        $xcatmaster = $ent->{xcatmaster};
+                    } else {
+                        $xcatmaster = '!myipfn!';
+                    }
+                    $kcmdline .= " local_boot_trigger=http://$xcatmaster/xcatrhevh/rhevh_finish_install/\@HOSTNAME\@";
+            
+                    $bptab->setNodeAttribs($node,
+                        { kernel   => $k,
+                          initrd   => $i,
+                          kcmdline => $kcmdline});
+            
+                }
+            }
+        }
+    }
+}
+
+# Generate the REST API http request 
+# $method: GET, PUT, POST, DELETE
+# $api: the url of rest api
+# $content: an xml section which including the data to perform the rest api
+sub genreq {
+    my $rhevm = shift;
+    my $method = shift;
+    my $api = shift;
+    my $content = shift;
+
+    if (! defined($content)) { $content = ""; }
+    my $header = HTTP::Headers->new('content-type' => 'application/xml',
+                             'Accept' => 'application/xml',
+                             #'Connection' => 'keep-alive',
+                             'Host' => $rhevm->{name}.':8443');
+    $header->authorization_basic($rhevm->{user}.'@internal', $rhevm->{pw});
+
+    my $ctlen = length($content);
+    $header->push_header('Content-Length' => $ctlen);
+
+    my $url = "https://".$rhevm->{name}.":8443".$api;
+    my $request = HTTP::Request->new($method, $url, $header, $content);
+
+    return $request;
+}
+
+# Make connection to rhev-m
+# Send REST api request to rhev-m
+# Receive the response from rhev-m
+# Handle the error cases
+#
+# return 1-ssl connection error; 
+#          2-http response error; 
+#          3-return a http error message; 
+#          5-operation failed
+sub send_req {
+    my $ref_rhevm = shift;
+    my $request = shift;
+
+    my $rhevm = $ref_rhevm->{name};
+
+    my $rc = 0;
+    my $response;
+    my $connect;
+    my $socket = IO::Socket::INET->new( PeerAddr => $rhevm, 
+                                                              PeerPort => '8443',
+                                                              Timeout => 15);
+    if ($socket) {
+        $connect = IO::Socket::SSL->start_SSL($socket, SSL_ca_file => "/etc/xcat/rhevm/$rhevm/ca.crt", Timeout => 0);
+        if ($connect) {
+            my $flags=fcntl($connect,F_GETFL,0);
+            $flags |= O_NONBLOCK;
+            fcntl($connect,F_SETFL,$flags);
+        } else {
+            $rc = 1;
+            $response = "Could not make ssl connection to $rhevm:8443.";
+        }
+    } else {
+        $rc = 1;
+        $response = "Could not create socket to $rhevm:8443.";
+    }
+
+    if ($rc) {
+        return ($rc, $response);
+    }
+
+    my $IOsel = new IO::Select;
+    $IOsel->add($connect);
+
+    if ($verbose) {
+        my $rsp;
+        push @{$rsp->{data}}, "\n===================================================\n$request----------------";
+        xCAT::MsgUtils->message("I", $rsp, $global_callback);
+    }
+
+    print $connect $request;
+    $response = "";
+    while (1) {
+        my $readbytes;
+        $IOsel->can_read(0.5);
+        do { $readbytes=sysread($connect,$response,65535,length($response)); } while ($readbytes);
+        if ($response) {
+            #return $response;
+            last;
+        } else {
+            if (not defined $readbytes and $! == EAGAIN) { next; }
+            $rc = 2;
+            last;
+        }
+    }
+
+    if ($verbose) {
+        my $rsp;
+        push @{$rsp->{data}}, "$response===================================================\n";
+        xCAT::MsgUtils->message("I", $rsp, $global_callback);
+    }
+
+    $IOsel->remove($connect);
+    close($connect);
+
+    if ($response) {
+        if (grep (/<html>/, $response)) { # get a error message in the html
+            $rc = 3; 
+        }  elsif (grep (/<\?xml/, $response)) {
+            my $parser = XML::LibXML->new();
+            my $doc = $parser->parse_string($response);
+            if ($doc ) {
+                my $attr;
+                if ($attr = getAttr($doc, "/fault/detail")) {
+                    $response = $attr;
+                    $rc = 5;
+                } elsif ($attr = getAttr($doc, "/action/fault/detail")) {
+                    if ($attr eq "[]") {
+                        if ($attr = getAttr($doc, "/action/fault/reason")) {
+                            $response = $attr;
+                        } else {
+                            $response = "failed";
+                        }
+                    } else {
+                        $response = $attr;
+                    }
+                    $rc = 5;
+                }
+            }
+        }
+   }
+    
+    return ($rc, $response);
+}
+
+# Add the rhels host since it cannot register automatically.
+sub addhost {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+
+    my @domain = xCAT::Utils->get_site_attribute("domain");
+    if (!$domain[0]) {
+        my $rsp;
+        push @{$rsp->{data}}, "The site.domain must be set to enable the rhev support.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return;
+    }
+
+    # Create the xml data
+    my $doc = XML::LibXML->createDocument();
+    my $root = $doc->createElement("host");
+    $doc->setDocumentElement($root);
+    my $name_ele = $doc->createElement("name");
+    $root->appendChild($name_ele);
+    my $name_t = XML::LibXML::Text->new("");
+    $name_ele->appendChild($name_t);
+    
+    my $add_ele = $doc->createElement("address");
+    $root->appendChild($add_ele);
+    my $add_t = XML::LibXML::Text->new("");
+    $add_ele->appendChild($add_t);
+    
+    my $rootpw_ele= $doc->createElement("root_password");
+    $root->appendChild($rootpw_ele);
+    my $rootpw_t = XML::LibXML::Text->new("");
+    $rootpw_ele->appendChild($rootpw_t);
+    
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if ($rhevh eq $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}->[0]) {
+                    # Create the host first
+                    my $api = "/api/hosts";
+                    my $method = "POST";
+
+                    # Generate the content
+                    $name_t->setData($rhevh);
+                    my $addofrhevh = $rhevh.".".$domain[0];
+                    $add_t->setData($addofrhevh);
+                    $rootpw_t->setData($rhevm_hash->{$rhevm}->{host}->{$rhevh}->{pw});
+                    $rootpw_t->setData('$1$c5TJgKlJ$CuO6rR5B3d5mZc3Etu9HZ1');
+                    my $content = $doc->toString();
+                    
+                    my $request = genreq($ref_rhevm, $method, $api, $content);
+                    my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+
+                    my $rsp;
+                    if ($rc) {
+                        push @{$rsp->{data}}, "$rhevh: $response";
+                        next;
+                    } else {
+                        my $parser = XML::LibXML->new();
+                        my $doc = $parser->parse_string($response);
+                        if ($doc ) {
+                            my $attr;
+                            if ($attr = getAttr($doc, "/vms/hosts/status/state")) {
+                                push @{$rsp->{data}}, "$rhevh: state: $attr";
+                            }
+                        }
+                    }
+                }
+            }
+        } 
+    }
+    # Adding the host to rhevm
+}
+
+# name -> path mapping for the resource display
+my $display = {
+    'datacenters' => {
+        'description' => ["description"],
+        'storagetype' => ['storage_type'],
+        'storageformat' =>['storage_format'],
+        'state' => ['status/state'],
+    },
+    'clusters' => {
+        'description' => ["description"],
+        'cpu' => ["cpu", "id"],
+        'memory_overcommit' => ["memory_policy/overcommit", "percent"],
+        'memory_hugepage' => ["memory_policy/transparent_hugepages/enabled"],
+    },
+    'storagedomains' => {
+        'type' => ["type"],
+        'ismaster' => ["master"],
+        'storage_type' => ["storage/type"],
+        'storage_add' => ["storage/address"],
+        'storage_path' => ["storage/path"],
+        'available' => ["available"],
+        'used' => ["used"],
+        'committed' => ["committed"],
+        'storage_format' => ["storage_format"],
+        'status' => ["status/state"],
+    },
+    'networks' => {
+        'description' => ["description"],
+        'stp' => ["stp"],
+        'state' => ["status/state"],
+    },
+    'hosts' => {
+        'address' => ["address"],
+        'state' => ["status/state"],
+        'type' => ["type"],
+        'storage_manager' => ["storage_manager"],
+        'powermgt' => ["power_management/enabled"],
+        'powermgt_type' => ["power_management", "type"],
+        'powermgt_addr' => ["power_management/address"],
+        'powermgt_user' => ["power_management/username"],
+        'ksm' => ["ksm/enabled"],
+        'hugepages' => ["transparent_hugepages/enabled"],
+        'iscsi' => ["iscsi/initiator"],
+        'cpu' => ["cpu/name"],
+        'cpuspeed' => ["cpu/speed"],
+        'summary_active' => ["summary/active"],
+        'summary_migrating' => ["summary/migrating"],
+        'summary_total' => ["summary/total"],
+    },
+    'host_nics' => {
+        'network' => ["network", "id", "networks", "/network/name"],
+        'mac' => ["mac", "address"],
+        'ip' => ["ip", "address"],
+        'netmask' => ["ip", "netmask"],
+        'gateway' => ["ip", "gateway"],
+        'speed' => ["speed"],
+        'boot_protocol' => ["boot_protocol"],
+        'state' => ["status/state"],
+    },
+    'vms' => {
+        'memory' => ["memory"],
+        'state' => ["status/state"],
+        'type' => ["type"],
+        'cpusocket' => ["cpu/topology", "sockets"],
+        'cpucore' => ["cpu/topology", "cores"],
+        'bootorder' => ["os/boot", "dev"],
+        'display' => ["display/type"],
+        'start_time' => ["start_time"],
+        'creation_time' => ["creation_time"],
+        'stateless' => ["stateless"],
+        'placement_policy' => ["placement_policy/affinity"],
+        'memory_guaranteed' => ["memory_policy/guaranteed"],
+    },
+    'templates' => {
+        'memory' => ["memory"],
+        'state' => ["status/state"],
+        'type' => ["type"],
+        'cpusocket' => ["cpu/topology", "sockets"],
+        'cpucore' => ["cpu/topology", "cores"],
+        'bootorder' => ["os/boot", "dev"],
+        'display' => ["display/type"],
+        'creation_time' => ["creation_time"],
+        'stateless' => ["stateless"],
+    },
+    'disks' => {
+        'size' => ["size"],
+        'type' => ["type"],
+        'state' => ["status/state"],
+        'iftype' => ["interface"],
+        'format' => ["format"],
+        'bootable' => ["bootable"],
+        'storage_domains' => ["storage_domains/storage_domain", "id", "storagedomains", "/storage_domain/name"],
+    },
+    'nics' => {
+        'iftype' => ["interface"],
+        'mac' => ["mac", "address"],
+        'network' => ["network", "id", "networks", "/network/name"],
+    },
+};
+
+# Display the resource, it's called by lsvm and lsve
+# $reponse - xml response return from send_req
+# $type -datacenters, clusters, storagedomains ...
+# $prelead - space that will be displayed pre the real message
+# $criteria - 'dc=<name>' or 'name=<name>', only display when matchs
+sub displaysrc {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $response = shift;
+    my $type = shift;
+    my $prelead = shift;
+    my $criteria = shift;
+    my $individual = shift;
+
+    my @output;
+    my @displayed;
+    
+    my $prefix;
+    if ($type eq "datacenters") {
+        $prefix = "/data_centers/data_center";
+    } elsif ($type eq "clusters") {
+        $prefix = "/clusters/cluster";
+    } elsif ($type eq "storagedomains") {
+        if ($individual) {
+            $prefix = "/storage_domain";
+        } else {
+            $prefix = "/storage_domains/storage_domain";
+        }
+    } elsif ($type eq "networks") {
+        $prefix = "/networks/network";
+    } elsif ($type eq "hosts") {
+        $prefix = "/hosts/host";
+    } elsif ($type eq "vms") {
+        $prefix = "/vms/vm";
+    } elsif ($type eq "templates") {
+        $prefix = "/templates/template";
+    } elsif ($type eq "disks") {
+        $prefix = "/disks/disk";
+    } elsif ($type eq "nics") {
+        $prefix = "/nics/nic";
+    } elsif ($type eq "host_nics") {
+        $prefix = "/host_nics/host_nic";
+    } else {
+        return ();
+    }
+    
+    my $parser = XML::LibXML->new();
+    my $doc = $parser->parse_string($response);
+    if ($doc) {
+        my @nodes = $doc->findnodes($prefix);
+        foreach my $node (@nodes) {
+            # when crteria specified, the dc or name need to be checked
+            if ($criteria) {
+                my ($name, $value) = split('=', $criteria);
+                my $curval;
+                if ($name eq "dc") {
+                    my $cnode = $node->findnodes("data_center");
+                    if (defined($cnode->[0])) {
+                        $curval = $cnode->[0]->getAttribute("id");
+                    } else {
+                        next;
+                    }
+                } elsif ($name eq "name") {
+                    my $cnode = $node->findnodes("name");
+                    if (defined($cnode->[0])) {
+                        $curval = $cnode->[0]->textContent();
+                    } else {
+                        next;
+                    }
+                }
+
+                unless ($curval eq $value) {
+                    next;
+                }
+            }
+            
+            # Get the resource name first and display
+            my $objname = getAttr($node, "name");
+            push @displayed, getAttr($node, "", "id");
+            push @output, $prelead.$type.": [".$objname."]";
+
+            # Display each item for the specific type
+            foreach my $name (sort (keys %{$display->{$type}})) {
+                if (defined ($display->{$type}->{$name}->[2])) { # search the resource from the id
+                    # If the [3] and [4] params are specified, use the [0] and [1] to get the target resouce id,
+                    # Then search the resource of this id, [3] is type and [4] is the path to get the end message
+                    my $id = getAttr($node, $display->{$type}->{$name}->[0], $display->{$type}->{$name}->[1]);
+                    my $srctype = $display->{$type}->{$name}->[2];
+                    my $srcpath = $display->{$type}->{$name}->[3];
+                    my ($rc, $newid, $stat, $response) = search_src($ref_rhevm, $srctype, "/".$id, 1);
+                    unless ($rc) {
+                        my $parser = XML::LibXML->new();
+                        my $doc = $parser->parse_string($response);
+                        if ($doc ) {
+                            my $attr;
+                            if ($attr = getAttr($doc, $srcpath) || defined ($attr)) {
+                                push @output, $prelead."  ".$name.": ".$attr;
+                            }
+                        }
+                    }
+                } else {
+                    my $value = getAttr($node, $display->{$type}->{$name}->[0], $display->{$type}->{$name}->[1]);
+                    if (defined ($value)) {
+                        push @output, $prelead."  ".$name.": ".$value;
+                    }
+                }
+            }
+        }
+    }
+    
+    my $rsp;
+    if (@output) {
+        push @{$rsp->{data}}, @output;
+    }
+    xCAT::MsgUtils->message("I", $rsp, $callback);
+
+    return @displayed;
+}
+
+# Display the virtual environment
+# -t - type of resouce: dc - datacenter; cl - cluster; sd - storage domain; nw - network; tpl - template
+# -o - the object that needs to be displayed. It could be multiple objs separated with ','
+# -m - the rhevm that manage the resources
+sub lsve {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+    my $nodes = shift;
+
+    my @output;
+
+    my ($type, $objs, $mgr, $approve, $create, $update, $active, $network, $power, $remove);
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('t=s' => \$type,
+                        'o=s' => \$objs,
+                        'm=s' => \$mgr);
+    }
+
+    my $rhevm = (keys %{$rhevm_hash})[0];
+    my $ref_rhevm = {'name' => $rhevm, 
+                             'user' => $rhevm_hash->{$rhevm}->{user}, 
+                             'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+    my @objs;
+    if ($objs) {
+        @objs = split (',', $objs);
+    }
+    foreach my $obj (@objs) {
+        if ($type eq "dc") {
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "datacenters", $obj);
+            unless ($rc) {
+                displaysrc($callback, $ref_rhevm, $response, "datacenters", "");
+                my $dcid = $id;
+
+                # Display the cluster, storagedomain, network if requiring to display datacenter
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "clusters", "datacenter%3D$obj");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "clusters", "    ");
+                }
+                #($rc, $id, $stat, $response) = search_src($ref_rhevm, "storagedomains", "datacenter%3D$obj");
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "datacenters/$dcid/storagedomains:storagedomains");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "storagedomains", "    ");
+                }
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "networks");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "networks", "    ", "dc=$dcid");
+                }
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "templates", "datacenter%3D$obj");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "templates", "    ");
+                }
+            }
+        } elsif ($type eq "cl") {
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "clusters", "$obj");
+            unless ($rc) {
+                displaysrc($callback, $ref_rhevm, $response, "clusters", "");
+            }
+        } elsif ($type eq "sd") {
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "storagedomains", "$obj");
+            unless ($rc) {
+                displaysrc($callback, $ref_rhevm, $response, "storagedomains", "");
+            }
+        } elsif ($type eq "nw") {
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "networks");
+            unless ($rc) {
+                displaysrc($callback, $ref_rhevm, $response, "networks", "  ", "name=$obj");
+            }
+        } elsif ($type eq "tpl") {
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "templates", "$obj");
+            unless ($rc) {
+                displaysrc($callback, $ref_rhevm, $response, "templates", "");
+            }
+        } else {
+            my $rsp;
+            push @{$rsp->{data}}, "The type: $type is not supported.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return;
+        }
+    }
+    
+    return;
+}
+
+# Configure the rhev virtual environment
+# -t - type of resouce: dc - datacenter; cl - cluster; sd - storage domain; nw - network
+# -o - the object that needs to be configured. It could be multiple objs separated with ','
+# -m - the rhevm that manage the resources
+# -d - datacenter name that needs by creating
+# -c - creating a resource
+# -u - updating a resource
+# -g - activate a resource
+# -s - deactivate a resource
+# -a - attach a resource
+# -b - detach a resource
+# -r - delete a resource
+
+# Working format:
+# cfgve -t sd -m <mgr> -o <name> -c
+# cfgve -t sd -m <mgr> -o <name> -a/-g/-s
+# cfgve -t nw -m <mgr> -o < name> -c
+# cfgve -t tpl -m <mgr> -o <name> -r
+# 
+sub cfgve {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+    my $nodes = shift;
+
+    my ($type, $objlist, $mgr, $datacenter, $create, $update, $remove, $activate, $deactivate, $attach, $detach, $force, $stype, $cputype);
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('t=s' => \$type,
+                        'o=s' => \$objlist,
+                        'm=s' => \$mgr,
+                        'd=s' => \$datacenter,
+                        'c' => \$create,
+                        'u' => \$update,
+                        'g' => \$activate,
+                        's' => \$deactivate,
+                        'a' => \$attach,
+                        'b' => \$detach,
+                        'r' => \$remove,
+                        'f' => \$force,
+                        'k=s' => \$stype,
+                        'p=s' => \$cputype);
+    }
+
+    my $rhevm = (keys %{$rhevm_hash})[0];
+    my $ref_rhevm = {'name' => $rhevm, 
+                             'user' => $rhevm_hash->{$rhevm}->{user}, 
+                             'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+    my @objs;
+    if ($objlist) {
+        @objs = split (',', $objlist);
+    }
+    foreach my $obj (@objs) {
+        if ($type eq "sd") {
+            if ($create) {
+                if (mkSD($callback, $ref_rhevm, $obj)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: create storage domain succeeded.";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                    return;
+                }
+            } elsif ($activate || $deactivate || $attach || $detach || $remove) {
+                # get the name of datacenter
+                my $vsdtab = xCAT::Table->new('virtsd',-create=>0);
+                my $vsdent = $vsdtab->getAttribs({'node'=>$obj}, ['datacenter']);
+                my $datacenter = $vsdent->{datacenter};
+                unless ($datacenter) {
+                    $datacenter = "Default";
+                }
+                my ($rc, $dcid, $sdid, $stat);
+                ($rc, $dcid, $stat) = search_src($ref_rhevm, "datacenters", $datacenter);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: failed to get datacenter: $datacenter.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    return;
+                }
+                ($rc, $sdid, $stat) = search_src($ref_rhevm, "storagedomains", $obj);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: failed to get storagedomains: $obj.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    return;
+                }
+                if ($activate || $deactivate) {
+                    my $rsp;
+                    if (activate($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains/$sdid", $obj, $deactivate)) {
+                        push @{$rsp->{data}}, "$obj: failed.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    } else {
+                        push @{$rsp->{data}}, "$obj: succeeded.";
+                        xCAT::MsgUtils->message("I", $rsp, $callback);
+                    }
+                } elsif ($attach || $detach) {
+                    my $rsp;
+                    if (attach($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains", "storage_domain", $sdid, $detach)) {
+                        push @{$rsp->{data}}, "$obj: failed.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    } else {
+                        push @{$rsp->{data}}, "$obj: succeeded.";
+                        xCAT::MsgUtils->message("I", $rsp, $callback);
+                    }
+                } elsif ($remove) {
+                    if ($force) {
+                        # deactivate the storage domain
+                        activate($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains/$sdid", $obj, 1);
+                    
+                        # detach the storage domain to the datacenter
+                        attach($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains", "storage_domain", $sdid, 1);
+                    }
+    
+                    if (!deleteSD($callback, $ref_rhevm, "/api/storagedomains/$sdid", $obj)) {
+                        my $rsp;
+                        push @{$rsp->{data}}, "$obj: delete storage domain succeeded.";
+                        xCAT::MsgUtils->message("I", $rsp, $callback);
+                        return;
+                    }
+                }
+            } 
+        } elsif ($type eq "tpl") {
+            if ($remove) {
+                my ($rc, $tplid, $stat, $response) = search_src($ref_rhevm, "templates", "$obj");
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: cannot find the template: $obj.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                }
+                generalaction($callback, $ref_rhevm, "/api/templates/$tplid", "DELETE", 1);
+            }
+        } elsif ($type eq "nw") {
+            if ($create) {
+                # serach datacenter
+                unless ($datacenter) {
+                    $datacenter = "Default";
+                }
+                my ($rc, $dcid, $stat) = search_src($ref_rhevm, "datacenters", $datacenter);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: failed to get datacenter: $datacenter.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                
+                # create the network
+                my $api = "/api/networks";
+                my $method = "POST";
+                my $content = "<network><name>$obj</name><data_center id=\"$dcid\"/></network>";
+                my $request = genreq($ref_rhevm, $method, $api, $content);
+                my $response;
+                ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: $response";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: succeeded";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                    next;
+                }
+            } elsif ($remove) {
+                my ($rc, $nwid, $stat) = search_src($ref_rhevm, "networks", $obj);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: failed to get networks: $obj.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                generalaction($callback, $ref_rhevm, "/api/networks/$nwid", "DELETE", 1);
+            }
+        } elsif ($type eq "dc") {
+            my ($rc, $dcid, $stat, $response) = search_src($ref_rhevm, "datacenters", "$obj");
+            
+            if ($create) {
+                if (!$rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: data center has been created.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+
+                unless ($stype && $stype =~ /^(nfs|localfs)$/) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: the storage type needs to be specified by -k.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                # create the datacenter
+                my $api = "/api/datacenters";
+                my $method = "POST";
+                my $content = "<data_center><name>$obj</name><storage_type>$stype</storage_type><version minor=\"0\" major=\"3\"/></data_center>";
+                my $request = genreq($ref_rhevm, $method, $api, $content);
+                my $response;
+                ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: $response";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: succeeded";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                    next;
+                }
+            } elsif ($remove) {
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: cannot find the data center.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                }
+                generalaction($callback, $ref_rhevm, "/api/datacenters/$dcid", "DELETE", 1);
+            }
+        } elsif ($type eq "cl") {
+            my ($rc, $clid) = search_src($ref_rhevm, "clusters", "$obj");
+            
+            if ($create) {
+                if (!$rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: cluster has been created.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+
+                unless ($datacenter) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: the datacenter for the cluster must be specified.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                my $dcid;
+                ($rc, $dcid) = search_src($ref_rhevm, "datacenters", "$datacenter");
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: failed to get the datacenter: $datacenter.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+
+                unless ($cputype) {
+                    $cputype = "Intel Penryn Family";
+                }
+                
+                # create the datacenter
+                my $api = "/api/clusters";
+                my $method = "POST";
+                my $content = "<cluster><name>$obj</name><data_center id=\"$dcid\"/><cpu id=\"$cputype\"/></cluster>";
+                my $request = genreq($ref_rhevm, $method, $api, $content);
+                my $response;
+                ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: $response";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: succeeded";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                    next;
+                }
+            } elsif ($remove) {
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$obj: cannot find the cluster.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                }
+                generalaction($callback, $ref_rhevm, "/api/clusters/$clid", "DELETE", 1, $force);
+            }
+        } else {
+            my $rsp;
+            push @{$rsp->{data}}, "The type: $type is not supported.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return;
+        }
+    }
+                             
+}
+
+
+# configure host
+# -a: approve the host that can be managed by rhev-m
+# -n: configure the network for host
+# -p: configure the power management for host.  
+#      This will be used for rhev-m to check the power status of host, so that when SPM (Storage Pool Manager) host
+#      down, rhev-m could switch the SPM role to another host automatically.
+#      For rack mounted server, the ipmilan is used to do the power management. The IP of bmc and user:passwd are
+#      neccessary to be configured for power management.
+# -e: activate the host
+# -d: deactivate a host to maintanance mode
+sub cfghost {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $nodes = shift;
+    my $args = shift;
+
+    my ($approve, $network, $power, $activate, $deactivate, $remove, $force);
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('a' => \$approve,
+                        'n' => \$network,
+                        'p' => \$power,
+                        'e' => \$activate,
+                        'd' => \$deactivate,
+                        'r' => \$remove,
+                        'f' => \$force);
+    }
+
+    # Set the default user:pw for ipmi
+    my ($ipmiuser, $ipmipw) = ('USERID', 'PASSW0RD');
+    my ($hment, $ipmient);
+    my %hyper;
+
+    # get the IP, user, passwd for the bmc of the host if requiring to configure power management
+    if ($power) {
+        my $hmtab = xCAT::Table->new('nodehm',-create=>0);
+        $hment = $hmtab->getNodesAttribs($nodes,['mgt']);
+
+        my $ipmitab = xCAT::Table->new('ipmi',-create=>0);
+        $ipmient = $ipmitab->getNodesAttribs($nodes,['bmc', 'username', 'password']);
+
+        #get the default password for bmc
+        my $pwtab = xCAT::Table->new('passwd',-create=>0);
+        my $pwent = $pwtab->getAttribs({'key'=>'ipmi'},['username', 'password']);
+        if ($pwent) {
+            $ipmiuser = $pwent->{'username'};
+            $ipmipw = $pwent->{'password'};
+        }
+    }
+
+    # get the network parameters for the host if requiring to configure the network for host
+    if ($network || $approve) {
+        # get the network interface for host
+        my $hyptab = xCAT::Table->new('hypervisor',-create=>0);
+        my $hypent = $hyptab->getNodesAttribs($nodes,['interface', 'datacenter', 'cluster']);
+        foreach my $node (@$nodes) {
+            if (defined ($hypent->{$node}->[0])) {
+                $hyper{$node}{interface} = $hypent->{$node}->[0]->{interface};
+                $hyper{$node}{datacenter} = $hypent->{$node}->[0]->{datacenter};
+                $hyper{$node}{cluster} = $hypent->{$node}->[0]->{cluster};
+            }
+            if (!$hyper{$node}{datacenter}) {
+                $hyper{$node}{datacenter} = "Default";
+            }
+            if (!$hyper{$node}{cluster}) {
+                $hyper{$node}{cluster} = "Default";
+            }
+        }
+    }
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm,
+                                 'user' => $rhevm_hash->{$rhevm}->{user},
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if ($rhevh eq $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}->[0]) {
+                    # get the host
+                    my ($rc, $hostid, $hoststat) = search_src($ref_rhevm, "hosts", $rhevh);
+                    if ($rc) {
+                        my $rsp;
+                        push @{$rsp->{data}}, "$rhevh: host was not created.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                        next;
+                    }
+
+                    if ($approve) {
+                      if ($hoststat eq "pending_approval") {
+                        # get the id of cluster
+                        my ($rc, $clusterid, $clusterstat) = search_src($ref_rhevm, "clusters", $hyper{$rhevh}{cluster});
+                        if ($rc) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$rhevh: failed to get cluster: $hyper{$rhevh}{cluster}.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                        my $approved = 0;
+                        # Create the host first
+                        my $api = "/api/hosts/$hostid/approve";
+                        my $method = "POST";
+
+                        # Generate the content
+                        my $content = "<action><cluster id=\"$clusterid\"/></action>";
+
+                        my $request = genreq($ref_rhevm, $method, $api, $content);
+                        my $response;
+                        ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                        
+                        if ($rc) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$rhevh: $response";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        } else {
+                            my $parser = XML::LibXML->new();
+                            my $doc = $parser->parse_string($response);
+                            if ($doc ) {
+                                my $attr;
+                                if ($attr = getAttr($doc, "/action/status/state")) {
+                                    if ($attr eq "complete") {
+                                        $approved = 1;
+                                    }
+                                }
+                            }
+                        }
+
+                        my $rsp;
+                        if ($approved) {
+                            push @{$rsp->{data}}, "$rhevh: approved.";
+                            xCAT::MsgUtils->message("I", $rsp, $callback);
+                        } else {
+                            push @{$rsp->{data}}, "$rhevh: failed to approve.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                      } else {
+                          my $rsp;
+                          push @{$rsp->{data}}, "$rhevh: the state of node is not correct for approve. Current state: $hoststat";
+                          xCAT::MsgUtils->message("E", $rsp, $callback);
+                      }
+                    }
+
+                    if ($activate || $deactivate) {
+                        my $rsp;
+                        if (activate($callback, $ref_rhevm,"/api/hosts/$hostid", $rhevh, $deactivate)) {
+                            push @{$rsp->{data}}, "$rhevh: failed.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                        } else {
+                            push @{$rsp->{data}}, "$rhevh: succeeded.";
+                            xCAT::MsgUtils->message("I", $rsp, $callback);
+                        }
+                    }
+                    
+                    # configure the network interface for a host
+                    if ($network) {
+                        unless ($hyper{$rhevh}{interface}) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$rhevh: the hypervisor.interface needs to be configured to configure the network for a host.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                        
+                        if ($hoststat eq "maintenance") {
+                            cfghypnw($callback, $ref_rhevm, $rhevh, $hyper{$rhevh}{interface}, $hyper{$rhevh}{datacenter});
+                        } else {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$rhevh: the hypervisor needs to be deactivated to maintenance state for the network configuring.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                    }
+
+                    if ($power) {
+                        # Configure the power management for a host
+                        # for rack mounted machine, use the 'ipmilan' type of power management
+                        if (defined($hment->{$rhevh}->[0]) && $hment->{$rhevh}->[0]->{'mgt'}) {
+                            if ($hment->{$rhevh}->[0]->{'mgt'} eq "ipmi") {
+                                # get the bmc IP, user, password for the bmc
+                                my ($user, $pw, $addr) = ($ipmiuser, $ipmipw);
+                                if (defined($ipmient->{$rhevh}->[0]) && $ipmient->{$rhevh}->[0]->{bmc}) {
+                                    $addr = $ipmient->{$rhevh}->[0]->{bmc};
+                                } else {
+                                    my $rsp;
+                                    push @{$rsp->{data}}, "$rhevh: the ipmi.bmc was not set to know the hardware control point.";
+                                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                                    next;
+                                }
+                                if (defined($ipmient->{$rhevh}->[0]) && $ipmient->{$rhevh}->[0]->{username}) {
+                                    $user = $ipmient->{$rhevh}->[0]->{username};
+                                }
+                                if (defined($ipmient->{$rhevh}->[0]) && $ipmient->{$rhevh}->[0]->{password}) {
+                                    $pw = $ipmient->{$rhevh}->[0]->{password};
+                                }
+
+                                my $doc = XML::LibXML->createDocument();
+                                my $root = $doc->createElement("host");
+                                $doc->setDocumentElement($root);
+                                my $pm_ele = $doc->createElement("power_management");
+                                $root->appendChild($pm_ele);
+                                $pm_ele->setAttribute("type", "ipmilan");
+
+                                $pm_ele->appendTextChild("enabled", "true");
+                                $pm_ele->appendTextChild("address", $addr);
+                                $pm_ele->appendTextChild("username", $user);
+                                $pm_ele->appendTextChild("password", $pw);
+
+                                my $api = "/api/hosts/$hostid";
+                                my $method = "PUT";
+
+                                my $request = genreq($ref_rhevm, $method, $api, $doc->toString);
+                                my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+
+                                my $rsp;
+                                if ($rc) {
+                                    push @{$rsp->{data}}, "$rhevh: $response";
+                                    next;
+                                } else {
+                                    push @{$rsp->{data}}, "$rhevh: Setting power management: $addr";
+                                }
+                                xCAT::MsgUtils->message("I", $rsp, $callback);
+                            } else {
+                                my $rsp;
+                                push @{$rsp->{data}}, "$rhevh: the supported power management method: ipmi.";
+                                xCAT::MsgUtils->message("E", $rsp, $callback);
+                            }
+                        } else {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$rhevh: the nodehm.mgt was not set to know the management method.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                        }
+                    } # end of power management configure
+
+                    if ($remove) {
+                        if ($force) {
+                            # deactivate the host anyway
+                            activate($callback, $ref_rhevm,"/api/hosts/$hostid", $rhevh, 1);
+                            if (waitforcomplete($ref_rhevm, "/api/hosts/$hostid", "/host/status/state=maintenance", 30)) {
+                                my $rsp;
+                                push @{$rsp->{data}}, "$rhevh: failed to waiting the host gets to \"maintenance\" state.";
+                                xCAT::MsgUtils->message("E", $rsp, $callback);
+                                next;
+                            }
+                        }
+                        generalaction($callback, $ref_rhevm, "/api/hosts/$hostid", "DELETE", 1);
+                    }
+                }
+            } # end of for each host
+        }
+    }
+}
+
+
+sub rmhost {
+}
+
+# List the host and virtual machine
+# -s short
+# -v display virtual machines which belongs to the host
+sub lsvm {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+    my $nodes = shift;
+
+    my ($short, $vm4host);
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('s' => \$short,
+                        'v' => \$vm4host);
+    }
+    
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+    
+        # Get the node that will be handled
+        my @vms;
+        my @hyps;
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    foreach my $node (@{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}}) {
+                        if ($rhevh eq $node) {
+                            push @hyps, $rhevh;
+                        } else {
+                            push @vms, $node;
+                        }
+                    }
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+            push @vms, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        foreach my $hyp (@hyps) {
+            # Get the host
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "hosts", "$hyp");
+            unless ($rc) {
+                my @hostids = displaysrc($callback, $ref_rhevm, $response, "hosts", "");
+
+                # display the nics for the vm
+                my $hostid = $hostids[0];
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "hosts:host_nics", "/$hostid/nics");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "host_nics", "    ");
+                }
+
+                # TODO, display the vm for host always?
+                if (1||$vm4host) {
+                    my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "vms", "Host.name%3D$hyp");
+                    unless ($rc) {
+                        displaysrc($callback, $ref_rhevm, $response, "vms", "    ");
+                    }
+                }
+            }
+        }
+
+        # Display virtual machines
+        foreach my $vm (@vms) {
+            # Get vm
+            my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "vms", $vm);
+            unless ($rc) {
+                my @vmids = displaysrc($callback, $ref_rhevm, $response, "vms", "");
+                
+                # display the disks for the vm
+                my $vmid = $vmids[0];
+                my ($rc, $id, $stat, $response) = search_src($ref_rhevm, "vms:disks", "/$vmid/disks");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "disks", "    ");
+                }
+                    
+                # display the nics for the vm
+                ($rc, $id, $stat, $response) = search_src($ref_rhevm, "vms:nics", "/$vmid/nics");
+                unless ($rc) {
+                    displaysrc($callback, $ref_rhevm, $response, "nics", "    ");
+                }
+            }
+        }
+    }
+}
+
+# Create virtual machine
+# Since the configuration for a vm is complicated, all the parameters will be gotten from vm table
+sub mkvm {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $nodes = shift;
+
+    my $upmac;  # used to update the mac table
+    my $mactab = new xCAT::Table('mac',-create=>1);
+
+    # Get the attributes for the node from the vm table
+    my $vmtab = xCAT::Table->new('vm',-create=>0);
+    my $vment = $vmtab->getNodesAttribs($nodes,['template', 'host', 'cluster', 'virtflags', 'storage', 'storagemodel', 'memory', 'cpus', 'nics', 'nicmodel', 'bootorder', 'vidproto']);
+
+    # Generate the xml content for add the storage
+    # Note: this is an independent action after the vm creating
+    my $adds = XML::LibXML->createDocument();
+    my $asroot = $adds->createElement("disk");
+    $adds->setDocumentElement($asroot);
+
+    # set the disk type: system and data
+    my $disktype_ele = $adds->createElement("type");
+    $asroot->appendChild($disktype_ele);
+    my $disktype_t = XML::LibXML::Text->new("system");
+    $disktype_ele->appendChild($disktype_t);
+
+    # set the bootable
+    my $diskboot_ele = $adds->createElement("bootable");
+    $asroot->appendChild($diskboot_ele);
+    my $diskboot_t = XML::LibXML::Text->new("true");
+    $diskboot_ele->appendChild($diskboot_t);
+    
+    my $sd_ele = $adds->createElement("storage_domains");
+    $asroot->appendChild($sd_ele);
+    my $sdid_ele = $adds->createElement("storage_domain");
+    $sd_ele->appendChild($sdid_ele);
+
+    # add size of disk
+    my $sdsize_ele = $adds->createElement("size");
+    $asroot->appendChild($sdsize_ele);
+    my $sdsize_t = XML::LibXML::Text->new("");
+    $sdsize_ele->appendChild($sdsize_t);
+
+   # add the element for type of disk interface 
+    my $sdif_ele = $adds->createElement("interface");
+    $asroot->appendChild($sdif_ele);
+    my $sdif_t = XML::LibXML::Text->new("virtio");
+    $sdif_ele->appendChild($sdif_t);
+
+    # add the disk format element
+    my $sdft_ele = $adds->createElement("format");
+    $asroot->appendChild($sdft_ele);
+    my $sdfm_t = XML::LibXML::Text->new("cow");
+    $sdft_ele->appendChild($sdfm_t);
+
+    # Generate the xml content for add network interface
+    # Note: this is an independent action after the vm creating
+    my $addnw = XML::LibXML->createDocument();
+    my $anwroot = $addnw->createElement("nic");
+    $addnw->setDocumentElement($anwroot);
+
+    # add the interface type element
+    my $nwif_ele = $addnw->createElement("interface");
+    $anwroot->appendChild($nwif_ele);
+    my $nwif_t = XML::LibXML::Text->new("virtio");
+    $nwif_ele->appendChild($nwif_t);
+
+    # add the name element
+    my $nwname_ele = $addnw->createElement("name");
+    $anwroot->appendChild($nwname_ele);
+    my $nwname_t = XML::LibXML::Text->new("nic1");
+    $nwname_ele->appendChild($nwname_t);
+
+    # add the network element which specify which network this nic 
+    # will be added to
+    my $nwnw_ele = $addnw->createElement("network");
+    $anwroot->appendChild($nwnw_ele);
+    my $nwnwname_ele = $addnw->createElement("name");
+    $nwnw_ele->appendChild($nwnwname_ele);
+    my $nwnwname_t = XML::LibXML::Text->new("rhevm");
+    $nwnwname_ele->appendChild($nwnwname_t);
+
+    # create a mac element
+    my $nwmac_ele = $addnw->createElement("mac");
+    
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my %node_hyp;
+        my %hostid;
+        my $success = 0;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+    
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    foreach (@{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}}) {
+                        $node_hyp{$_}{hyp} = $rhevh;
+                        $hostid{$rhevh} = 1;
+                    }
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+            foreach (@{$rhevm_hash->{$rhevm}->{node}}) {
+                $node_hyp{$_}{hyp} = "";
+            }
+        }
+
+        # get the host id
+        # this is used for the case that needs locate vm to a spcific host
+        foreach my $host (keys %hostid) {
+            my ($rc, $id, $stat) = search_src($ref_rhevm, "hosts", $host);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "Cannot find $host in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                return;
+            }
+            $hostid{$host} = $id;
+        }
+        my @nodes = (keys %node_hyp);
+        my $macmac = $mactab->getNodesAttribs(\@nodes, ['mac']);
+   
+        foreach my $node (@nodes) {
+            my $myvment = $vment->{$node}->[0];
+            unless ($myvment) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: has NOT entry in vm table.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+            
+            # Check the existence of the node
+            my ($rc, $id, $stat) = search_src($ref_rhevm, "vms", $node);
+            if (!$rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: virtual machine has been created.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+                next;
+            }
+            
+            #Create the virtual machine first
+            my $api = "/api/vms";
+            my $method = "POST";
+            
+            # generate the content
+            # configure the template
+            my $hastpl = 0;
+            my $tplele;
+            if ($myvment->{template}) {
+                $tplele = "<template><name>$myvment->{template}</name></template>";
+                $hastpl = 1;
+            } else {
+                $tplele = "<template><name>Blank</name></template>";
+            }
+            
+            # configure memory
+            my $memele;
+            if ($myvment->{memory}) {
+                my $memsize = $myvment->{memory};
+                $memsize =~ s/g/000000000/i;
+                $memsize =~ s/m/000000/i;
+                $memele = "<memory>$memsize</memory>";
+            } elsif (!$hastpl) {
+                $memele = "<memory>2000000000</memory>";
+            }
+            
+            # set the cpu
+            my $cpuele;
+            if ($myvment->{cpus}) {
+                my ($socketnum, $corenum) = split(':', $myvment->{cpus});
+                unless ($corenum) {$corenum = 1;}
+                $cpuele = "<cpu><topology cores=\"$socketnum\" sockets=\"$corenum\"/></cpu>";
+            } elsif (!$hastpl) {
+                $cpuele = "<cpu><topology cores=\"1\" sockets=\"1\"/></cpu>"
+            }
+            
+            # configure bootorder
+            # there's a bug that sequence is not correct to set two order, so currently just set one
+            my $boele;
+            if ($myvment->{bootorder}) {
+                my ($firstbr, $secbr) = split (',', $myvment->{bootorder});
+                if ($secbr) {
+                    $boele = "<os><boot dev=\"$firstbr\"/><boot dev=\"$secbr\"/><boot/></os>";
+                } else {
+                    $boele = "<os><boot dev=\"$firstbr\"/><boot/></os>";
+                }
+            } elsif (!$hastpl) {
+                $boele = "<os><boot dev=\"network\"/><boot/></os>";
+            }
+
+            my $disele;
+            if ($myvment->{vidproto}) {
+                $disele = "<display><type>$myvment->{vidproto}</type></display>";
+            } elsif (!$hastpl) {
+                $disele = "<display><type>vnc</type></display>";
+            }
+
+            my $affinity;
+            if ($myvment->{virtflags}) {
+                # parse the specific parameters from vm.virtflags
+                my @pairs = split (':', $myvment->{virtflags});
+                foreach my $pair (@pairs) {
+                    my ($name, $value) = split('=', $pair);
+                    if ($name eq "placement_affinity") {
+                        # set the affinity for placement_policy
+                        $affinity = "<affinity>$value</affinity>"
+                    }
+                }
+            }
+
+            if (!$affinity && !$hastpl) {
+                $affinity = "<affinity>migratable</affinity>"
+            }
+
+            my $hostele;
+            if ($myvment->{host}) {
+                $hostele = "<host id=\"$hostid{$myvment->{host}}\"/>";
+            }
+
+            my $placement_policy = "<placement_policy>$hostele$affinity</placement_policy>";
+
+            # set the cluster for the vm
+            my $clusterele;
+            if ($myvment->{cluster}) {
+                $clusterele = "<cluster><name>$myvment->{cluster}</name></cluster>";
+            } else {
+                $clusterele = "<cluster><name>Default</name></cluster>";
+            }
+
+            my $content = "<vm><type>server</type><name>$node</name>$clusterele$tplele$memele$cpuele$boele$placement_policy$disele</vm>";
+            my $request = genreq($ref_rhevm, 
+                               $method,
+                               $api,
+                               $content);
+            my $response;
+            my $vmid;
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+            if (!$rc) {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                my $newvm;
+                if (defined ($doc->findnodes("/vm/name")->[0])) {
+                    $newvm = $doc->findnodes("/vm/name")->[0]->textContent();
+                }
+                if ($newvm ne $node) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: create virtual machine failed.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                my $vm = $doc->findnodes("/vm")->[0];
+                $vmid = $vm->getAttribute('id');
+                $success = 1;
+            } else {
+                my $rsp;
+                push @{$rsp->{data}}, $response;
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+    
+            #Add the disk for the vm from storage domain
+            #Get the storage domain by name
+            my ($sdname, $disksize, $disktype) = split(':', $myvment->{storage});
+            if ($sdname) {
+                if (waitforcomplete($ref_rhevm, "/api/vms/$vmid", "/vm/status/state=down", 30)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: failed to waiting the vm gets to \"down\" state.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+                $success = 0;
+                my $sdid;
+                ($rc, $sdid, $stat) = search_src($ref_rhevm, "storagedomains", $sdname);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "Could not get the storage domain $sdname.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                } 
+
+                if ($sdid) {
+                    $api = "/api/vms/$vmid/disks";
+                    $method = "POST";
+                    
+                    # generate the content
+                    if ($disktype) {
+                        $disktype_t->setData($disktype);
+                        if ($disktype eq "system") {
+                            $diskboot_t->setData("true");
+                        } else {
+                            $diskboot_t->setData("false");
+                        }
+                    } else {
+                        $disktype_t->setData("system");
+                        $diskboot_t->setData("true");
+                    }
+                    # set the size of disk
+                    if ($disksize) {
+                        $disksize =~ s/g/000000000/i;
+                        $disksize =~ s/m/000000/i;
+                    } else {
+                        $disksize = "5000000000"; #5G is default
+                    }
+                    $sdid_ele->setAttribute("id", $sdid);
+                    $sdsize_t->setData($disksize);
+
+                    # set the interface type and format for disk
+                    if ($myvment->{storagemodel}) {
+                        my ($iftype,$iffmt) = split(':', $myvment->{storagemodel});
+                        $sdif_t->setData($iftype);
+                        $sdfm_t->setData($iffmt);
+                    } else {
+                        $sdif_t->setData("virtio");
+                        $sdfm_t->setData("cow");
+                    }
+    
+                    $request = genreq($ref_rhevm, $method, $api, $adds->toString());
+                    ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                    if (!$rc) {
+                        my $parser = XML::LibXML->new();
+                        my $doc = $parser->parse_string($response);
+                        if (defined($doc->findnodes("/fault")->[0])) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$node: Add disk failed for virtual machine";
+                            if ($doc->findnodes("/fault/detail")->[0]) {
+                                push @{$rsp->{data}}, $doc->findnodes("/fault/detail")->[0]->textContent();
+                            }
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                        my $state;
+                        if (defined($doc->findnodes("/disk/creation_status/state")->[0])) {
+                            $state = $doc->findnodes("/disk/creation_status/state")->[0]->textContent();
+                        }
+                        if ($state =~ /fail/i) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$node: failed to add the disk.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                        $success = 1;
+                    } else {
+                        my $rsp;
+                        push @{$rsp->{data}}, $response;
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                        next;
+                    }
+                }
+            }
+            
+            # Add the network interface
+            #Get the network by name
+            my @nics;
+            if ($myvment->{nics}) {
+                @nics = split(/\|/, $myvment->{nics});
+            }
+            if (!@nics && !$hastpl) {
+                # default is to add nic1 to manament network 'rhevm'
+                push @nics, "rhevm:eth0:yes";
+            }
+            if (@nics) {
+                if (waitforcomplete($ref_rhevm, "/api/vms/$vmid", "/vm/status/state=down", 30)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: failed to waiting the vm gets to \"down\" state.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+            }
+            foreach my $nic (@nics) {
+                $success = 0;
+                # format of nic: [networkname:ifname:installnic]
+                my ($nwname, $ifname, $instnic) = split(':', $nic);
+            
+                my $nwid;
+                ($rc, $nwid, $stat) = search_src($ref_rhevm, "networks", "$nwname");
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "Could not get the network $nwname.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                } 
+                $api = "/api/vms/$vmid/nics";
+                $method = "POST";
+                
+                # generate the content
+                # set the nic interface type
+                if ($myvment->{nicmodel}) {
+                    $nwif_t->setData($myvment->{nicmodel});
+                } else {
+                    $nwif_t->setData("virtio");
+                }
+                $nwname_t->setData($ifname);
+                $nwnwname_t->setData($nwname);
+
+                # set the mac address element
+                # if no entry in mac.mac, and this is install nic, THEN use the existed mac
+                # otherwise create a new mac automatically by rhev-m
+                my $orgmac;
+                if ($instnic && defined ($macmac->{$node}->[0]) && defined ($macmac->{$node}->[0]->{'mac'})) {
+                    $orgmac = $macmac->{$node}->[0]->{'mac'};
+                    $anwroot->appendChild($nwmac_ele);
+                    $nwmac_ele->setAttribute("address", $orgmac);
+                } else {
+                    $anwroot->removeChild($nwmac_ele);
+                }
+                
+                $content = $addnw->toString();
+                $request = genreq($ref_rhevm, 
+                                   $method,
+                                   $api,
+                                   $content);
+                ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                if (!$rc) {
+                    my $parser = XML::LibXML->new();
+                    my $doc = $parser->parse_string($response);
+                    if (defined($doc->findnodes("/nic/mac")->[0])) {
+                        my $realmac = $doc->findnodes("/nic/mac")->[0]->getAttribute("address");
+                        if (! $orgmac && $instnic) {
+                            $upmac->{$node}->{mac} = $realmac;
+                        }
+                        
+                        $success = 1;
+                        next;
+                     } else {
+                        my $rsp;
+                        push @{$rsp->{data}}, "$node: failed to create virtual machine.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                        next;
+                    }
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, $response;
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+            }
+
+            if ($success) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: Succeeded";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+            }
+        }
+    }
+
+    $mactab->setNodesAttribs($upmac);
+}
+
+# Remove a virtual machine
+sub rmvm {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+
+    my $force;
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('f' => \$force);
+    }
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my @nodes;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        # perform the action against the node
+        foreach my $node (@nodes) {
+            # Get the ID of node
+            my ($rc, $id, $state) = search_src($ref_rhevm, "vms", $node);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            } elsif (! defined($id)) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+
+            # Remove the vm
+            my $api = "/api/vms/$id";
+            my $method = "DELETE";
+            
+            my $content = "<action/>";
+            if ($force) {
+                $content = "<action><force>true</force></action>";
+            }
+            my $request = genreq($ref_rhevm, 
+                               $method,
+                               $api,
+                               $content);
+            my $response;
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+            if ($rc == 2) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: succeeded.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+                next;
+            } else {
+                my $rsp;
+                push @{$rsp->{data}}, $response;
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+        }
+    }
+}
+
+# Change virtual machine
+sub chvm {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $nodes = shift;
+
+    # Get the mac address for the nodes from the mac table
+    my $mactab = new xCAT::Table('mac',-create=>1);
+
+    # Get the attributes for the nodes from the vm table
+    my $vmtab = xCAT::Table->new('vm',-create=>0);
+    my $vment = $vmtab->getNodesAttribs($nodes,['template', 'host', 'cluster', 'virtflags', 'storage', 'storagemodel', 'memory', 'cpus', 'nics', 'nicmodel', 'bootorder', 'vidproto']);
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my %node_hyp;
+        my %hostid;
+        my $success = 0;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+    
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    foreach (@{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}}) {
+                        $node_hyp{$_}{hyp} = $rhevh;
+                        $hostid{$rhevh} = 1;
+                    }
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+            foreach (@{$rhevm_hash->{$rhevm}->{node}}) {
+                $node_hyp{$_}{hyp} = "";
+            }
+        }
+
+        # get the host id
+        # this is used for the case that needs locate vm to a spcific host
+        foreach my $host (keys %hostid) {
+            my ($rc, $id, $stat) = search_src($ref_rhevm, "hosts", $host);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "Cannot find $host in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                return;
+            }
+            $hostid{$host} = $id;
+        }
+        my @nodes = (keys %node_hyp);
+        my $macmac = $mactab->getNodesAttribs(\@nodes, ['mac']);
+   
+        foreach my $node (@nodes) {
+            my $myvment = $vment->{$node}->[0];
+            unless ($myvment) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: has NOT entry in vm table.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+            
+            # Check the existence of the node
+            my ($rc, $vmid, $stat) = search_src($ref_rhevm, "vms", $node);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: virtual machine was not created.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+                next;
+            }
+            
+            # generate the content
+            my $tplele;
+            if ($myvment->{template}) {
+                $tplele = "<template><name>$myvment->{template}</name></template>";
+            }
+            
+            # configure memory
+            my $memele;
+            if ($myvment->{memory}) {
+                my $memsize = $myvment->{memory};
+                $memsize =~ s/g/000000000/i;
+                $memsize =~ s/m/000000/i;
+                $memele = "<memory>$memsize</memory>";
+            }
+            
+            # set the cpu
+            my $cpuele;
+            if ($myvment->{cpus}) {
+                my ($socketnum, $corenum) = split(':', $myvment->{cpus});
+                unless ($corenum) {$corenum = 1;}
+                $cpuele = "<cpu><topology cores=\"$socketnum\" sockets=\"$corenum\"/></cpu>";
+            }
+            
+            # configure bootorder
+            # there's a bug that sequence is not correct to set two order, so currently just set one
+            my $boele;
+            if ($myvment->{bootorder}) {
+                my ($firstbr, $secbr) = split (',', $myvment->{bootorder});
+                if ($secbr) {
+                    $boele = "<os><boot dev=\"$firstbr\"/><boot dev=\"$secbr\"/><boot/></os>";
+                } else {
+                    $boele = "<os><boot dev=\"$firstbr\"/><boot/></os>";
+                }
+            }
+
+            my $disele;
+            if ($myvment->{vidproto}) {
+                $disele = "<display><type>$myvment->{vidproto}</type></display>";
+            }
+
+            my $affinity;
+            if ($myvment->{virtflags}) {
+                # parse the specific parameters from vm.virtflags
+                my @pairs = split (':', $myvment->{virtflags});
+                foreach my $pair (@pairs) {
+                    my ($name, $value) = split('=', $pair);
+                    if ($name eq "placement_affinity") {
+                        # set the affinity for placement_policy
+                        $affinity = "<affinity>$value</affinity>"
+                    }
+                }
+            }
+
+            my $hostele;
+            if ($myvment->{host}) {
+                $hostele = "<host id=\"$hostid{$myvment->{host}}\"/>";
+            }
+
+            my $placement_policy;
+            if ($affinity) {
+                $placement_policy = "<placement_policy>$hostele$affinity</placement_policy>";
+            } elsif ($hostele) {
+                $affinity = "<affinity>migratable</affinity>";
+                $placement_policy = "<placement_policy>$hostele$affinity</placement_policy>";
+            }
+
+            # set the cluster for the vm
+            my $clusterele;
+            if ($myvment->{cluster}) {
+                $clusterele = "<cluster><name>$myvment->{cluster}</name></cluster>";
+            }
+
+            my $api = "/api/vms/$vmid";
+            my $method = "PUT";
+            
+            my $content = "<vm><type>server</type><name>$node</name>$clusterele$tplele$memele$cpuele$boele$placement_policy$disele</vm>";
+            my $request = genreq($ref_rhevm, $method, $api, $content);
+            my $response;
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: $response";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            } else {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                my $state;
+                if ($node eq getAttr($doc, "/vm/name")) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: change vm completed.";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                    next;
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: change vm failed.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+            } 
+        }
+    }
+}
+
+# Clone the virtual machine
+# create template first
+sub clonevm {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+
+    my ($template, $basemaster);
+    if ($args) {
+        @ARGV=@{$args};
+        GetOptions('t=s' => \$template,
+                        'b' => \$basemaster);
+    }
+
+    my $ref_rhevm;
+    my @nodes;
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        # generate the hash of rhevm which will be used for the action functions
+        $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+    }
+
+    my $node = $nodes[0];
+    # create a template from a vm
+    if ($template) {
+        # Get the ID of node
+        my ($rc, $vmid, $state) = search_src($ref_rhevm, "vms", $node);
+        if ($rc) {
+            my $rsp;
+            push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return;
+        }
+
+        if ($state ne "down") {
+            my $rsp;
+            push @{$rsp->{data}}, "$node: vm needs to be shutdown to run the clone.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return;
+        }
+
+        my $api = "/api/templates";
+        my $method = "POST";
+        my $content = "<template><name>$template</name><vm id=\"$vmid\"/></template>";
+        my $request = genreq($ref_rhevm, $method, $api, $content);
+        my $response;
+        ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+        if ($rc) {
+            return (1, $response);
+        } else {
+            my $parser = XML::LibXML->new();
+            my $doc = $parser->parse_string($response);
+            if ($doc->findnodes("/template/status/state")->[0]) {
+                my $state = $doc->findnodes("/template/status/state")->[0]->textContent();
+    
+                my $rsp;
+                push @{$rsp->{data}}, "$template: $state.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+            } else {
+                my $rsp;
+                push @{$rsp->{data}}, "$template: failed to get the status.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+            }
+            return;
+        }
+    }
+
+}
+
+# Set the boot sequence for the vm
+sub rsetboot {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+
+    my ($showstat, $bootdev);
+    if ($args) {
+        my $arg = $args->[0];
+        if ($arg =~ /^stat/) {
+            $showstat = 1;
+        } else {
+            $bootdev = $arg;
+        }
+    } else {
+        $showstat = 1;
+    }
+
+    my ($firstbr, $secbr);
+    if ($bootdev) {
+        ($firstbr, $secbr) = split (',', $bootdev);
+        if (($firstbr && $firstbr !~ /^(network|hd)$/) || ($secbr && $secbr !~ /^(network|hd)$/)) {
+            my $rsp;
+            push @{$rsp->{data}}, "Supported boot device: network, hd";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return 1;
+        }
+    }
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my @nodes;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        foreach my $node (@nodes) {
+            # Get the ID of vm
+            my ($rc, $vmid, $state, $response) = search_src($ref_rhevm, "vms", $node);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+
+            if ($showstat) {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                my @bootdevs = getAttr($doc, "/vms/vm/os/boot", "dev");
+                my $bootlist = join(',', @bootdevs);
+                my $rsp;
+                push @{$rsp->{data}}, "$node: $bootlist";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+                next;
+            }
+
+            # configure bootorder
+            my $boele;
+            if ($secbr) {
+                $boele = "<os><boot dev=\"$firstbr\"/><boot dev=\"$secbr\"/><boot/></os>";
+            } else {
+                $boele = "<os><boot dev=\"$firstbr\"/><boot/></os>";
+            }
+
+            my $api = "/api/vms/$vmid";
+            my $method = "PUT";
+            
+            my $content = "<vm>$boele</vm>";
+            my $request = genreq($ref_rhevm, $method, $api, $content);
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: $response";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            } else {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: set boot order completed.";
+                xCAT::MsgUtils->message("I", $rsp, $callback);
+                next;
+            } 
+        }
+    }
+}
+
+#Migrate the virtual machine
+sub rmigrate {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+
+    my ($template, $basemaster);
+    unless ($args) {
+        my $rsp;
+        push @{$rsp->{data}}, "Needs a target host.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+    }
+
+    my $host = $args->[0];
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my @nodes;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        foreach my $node (@nodes) {
+            # Get the ID of vm
+            my ($rc, $vmid, $state) = search_src($ref_rhevm, "vms", $node);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+
+            my $hostid;
+            ($rc, $hostid, $state) = search_src($ref_rhevm, "hosts", $host);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$host: host was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+
+            # Remove the vm
+            my $api = "/api/vms/$vmid/migrate";
+            my $method = "POST";
+            
+            my $content = "<action><host id=\"$hostid\"/></action>";
+            my $request = genreq($ref_rhevm, $method, $api, $content);
+            my $response;
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: $response.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+            } else {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                if ($doc->findnodes("/action/status/state")->[0]) {
+                    my $state = $doc->findnodes("/template/status/state")->[0]->textContent();
+        
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: migrated to $host: $state.";
+                    xCAT::MsgUtils->message("I", $rsp, $callback);
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$node: failed to migrate to $host.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                }
+            }
+        }
+    }
+}
+
+# Hardware control 
+# rpower <vm> on/off/reset
+sub power {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $args = shift;
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my @nodes;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        # perform the action against the node
+        foreach my $node (@nodes) {
+            # Get the ID of node
+            my ($rc, $id, $state) = search_src($ref_rhevm, "vms", $node);
+            if ($rc) {
+                my $rsp;
+                push @{$rsp->{data}}, "$node: node was not defined in the rhevm.";
+                xCAT::MsgUtils->message("E", $rsp, $callback);
+                next;
+            }
+            
+            my $output;
+            if ($args->[0] eq 'on') {
+                if ($state eq "up" || $state eq "powering_up") {
+                    $output = "$node: on";
+                } else {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'start');
+                    if (!$rc) {
+                        $output = "$node: on";
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                }
+            } elsif ($args->[0] eq 'off') {
+                if ($state eq "down" || $state eq "powering_down" || $state eq "powered_down") {
+                    $output = "$node: off";
+                } else {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'stop');
+                    if (!$rc) {
+                        $output = "$node: off";
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                }
+            } elsif ($args->[0] eq 'reset' || $args->[0] eq 'boot') {
+                if ($state eq "up" || $state eq "powering_up") {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'stop');
+                    if (!$rc) {
+                        if (waitforcomplete($ref_rhevm, "/api/vms/$id", "/vm/status/state=down", 30)) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$node: failed to waiting the vm gets to \"down\" state.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                        }
+                        ($rc, $msg) = power_action($ref_rhevm, $id, 'start');
+                        if (!$rc) {
+                            $output = "$node: $args->[0]";
+                        } else {
+                            $output = "$node: $msg";
+                        }
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                } else {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'start');
+                    if (!$rc) {
+                        $output = "$node: $args->[0]";
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                }
+            } elsif ($args->[0] eq 'softoff') {
+                if ($state eq "down" || $state eq "powering_down" || $state eq "powered_down") {
+                    $output = "$node: softoff";
+                } else {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'shutdown');
+                    if (!$rc) {
+                        $output = "$node: softoff";
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                }
+            } elsif ($args->[0] eq 'suspend') {
+                if ($state eq "suspended") {
+                    $output = "$node: suspended";
+                } else {
+                    my ($rc, $msg) = power_action($ref_rhevm, $id, 'suspend');
+                    if (!$rc) {
+                        $output = "$node: suspended";
+                    } else {
+                        $output = "$node: $msg";
+                    }
+                }
+            } elsif ($args->[0] =~ /^stat/) {
+                if ($state eq "down") {
+                    $output = "$node: off";
+                } elsif ($state eq "up") {
+                    $output = "$node: on";
+                } else {
+                    $output = "$node: $state";
+                }
+            }
+            my $rsp;
+            push @{$rsp->{data}}, $output;
+            xCAT::MsgUtils->message("I", $rsp, $callback);
+        }
+    }
+
+}
+
+# Do the power control
+sub power_action {
+    my $rhevm = shift;
+    my $id = shift;
+    my $action = shift;
+    
+    my $api = "/api/vms/$id/$action";
+    my $method = "POST";
+    my $content = "<action/>";
+    my $request = genreq($rhevm, 
+                       $method,
+                       $api,
+                       $content);
+    my ($rc, $response) = send_req($rhevm, $request->as_string());
+    if ($rc) {
+        return (1, $response);
+    } else {
+        my $parser = XML::LibXML->new();
+        my $doc = $parser->parse_string($response);
+        my $state = $doc->findnodes("/action/status/state")->[0]->textContent();
+        return (0, $state);
+    }
+
+    return (1);
+}
+
+# Search resource inside rhev-m
+# $orgtype: format: [type] or [container:type]
+#               [type] could be: datacenter, cluster ...
+#               [container:type could be: 'vms:nics' ('vms' is the container of nic, 'nics' is the real type), vms:disk  
+# $node: could be name for a resource; or the path of resource when start with '/'
+#           if no $node specified, search all resource with the '$type'
+# $individual: do search for a resource individually
+#
+# return -1-parameter error; 11-nosuch id; 
+sub search_src {
+    my $rhevm = shift;
+    my $orgtype = shift;
+    my $node = shift;
+    my $individual = shift;
+
+    my $api;
+    my ($container, $type);
+    if ($orgtype =~ /:/) {
+        ($container, $type) = split (/:/, $orgtype);
+    } else {
+       $container = $type = $orgtype;
+    }
+
+    my $ispath;
+    if ($node) {
+        if ($node =~ /^\//) {
+            # is a path
+            $api = "/api/$container".$node;
+            $ispath = 1;
+        } else {
+            $api = "/api/$container?search=$node";
+        }
+    } else {
+        $api = "/api/$container";
+    }
+    my $method = "GET";
+    my $content = "";
+
+    my $request = genreq($rhevm, $method, $api, $content);
+    my ($rc, $response) = send_req($rhevm, $request->as_string());
+
+    if ($rc) {
+        return ($rc, $response);
+    } else {
+        my $parser = XML::LibXML->new();
+        my $doc = $parser->parse_string($response);
+        if ($doc ) {
+            my ($id, $state, $idstr, $ststr);
+            if ($type eq "vms") {
+                $idstr = "/vms/vm";
+            } elsif ($type eq "hosts") {
+                $idstr = "/hosts/host";
+            } elsif ($type eq "templates") {
+                $idstr = "/templates/template";
+            } elsif ($type eq "storagedomains") {
+                if ($individual) {
+                    $idstr = "/storage_domain";
+                } else {
+                    $idstr = "/storage_domains/storage_domain";
+                }
+            } elsif ($type eq "networks") {
+                if ($individual) {
+                    $idstr = "/network";
+                } else {
+                    $idstr = "/networks/network";
+                }                
+            } elsif ($type eq "datacenters") {
+                $idstr = "/data_centers/data_center";
+            } elsif ($type eq "clusters") {
+                $idstr = "/clusters/cluster";
+            } elsif ($type eq "disks") {
+                $idstr = "/disks/disk";
+            } elsif ($type eq "nics") {
+                $idstr = "/nics/nic";
+            } elsif ($type eq "host_nics") {
+                $idstr = "/host_nics/host_nic";
+            } else {
+                return (-1);
+            }
+
+            my $idnode;
+            # network is special that does not support to  serach a specific resource, 
+            # so have to do the search by code from all the output
+            if ($type eq "networks" && $node &&(!$ispath)) { 
+                my @nodes = $doc->findnodes($idstr);
+                foreach my $n (@nodes) {
+                    if ($node eq getAttr($n, "name")) {
+                        $idnode = $n;
+                        last;
+                    }
+                }
+            } else {
+                $idnode = $doc->findnodes($idstr)->[0];
+            }
+            if (defined $idnode) {
+              $id = $idnode->getAttribute('id');
+              if ($type eq "vms") {
+                  $ststr = "/vms/vm/status/state";
+              } elsif ($type eq "hosts") {
+                  $ststr = "/hosts/host/status/state";
+              } elsif ($type eq "templates") {
+                  $ststr = "/templates/template/status/state";
+              } elsif ($type eq "storagedomains") {
+                  if ($individual) {
+                      $ststr = "/storage_domain/storage/type";
+                  } else {
+                      $ststr = "/storage_domains/storage_domain/storage/type";
+                  }
+              } elsif ($type eq "networks") {
+                  $ststr = "status/state";
+                  $doc = $idnode;
+              } elsif ($type eq "datacenters") {
+                  $ststr = "/data_centers/data_center/status/state";
+              } elsif ($type eq "clusters") {
+                  $ststr = "/clusters/cluster/name";
+              } elsif ($type eq "disks") {
+                  $ststr = "/disks/disk/status/state";
+              } elsif ($type eq "nics") {
+                  $ststr = "/nics/nic/name";
+              } elsif ($type eq "host_nics") {
+                  $ststr = "/host_nics/host_nic/status/state";
+              } else {
+                  return (-1);
+              }
+              my $statenode = $doc->findnodes($ststr)->[0];
+              if (defined $statenode) {
+                $state = $statenode->textContent();
+              }
+
+              # no id was found
+              if (!$id) {
+                  return (11);
+              }
+              
+              return (0, $id, $state, $response);
+            } else {
+                return (11);
+            }
+        }
+    }
+
+    return (1);
+}
+
+# Get the value for a element from the xml of rest api response
+sub getAttr {
+    my $doc = shift;
+    my $path = shift;
+    my $att = shift;
+
+    my @nodes;
+    if ($path) {
+        # handle the cases that has multiple entries for one atributes like boot order
+        @nodes = $doc->findnodes($path);
+    } else {
+        push @nodes, $doc;
+    }
+    
+    if (@nodes) {
+        my @value;
+        foreach my $node (@nodes) {
+            if ($att) {
+                push @value, $node->getAttribute($att);
+            } else {
+                push @value, $node->textContent();
+            }
+        }
+        return join (',', @value);
+    } else {
+        return "";
+    }
+}
+
+# It's a command that will be triggered from the httpd when the installation of rhev-h has finished
+# Run nodeset and updatenodestat to update the status for the rhev-h
+sub rhevhupdateflag {
+    my $request = shift;
+    my $callback = shift;
+    my $subreq = shift;
+
+    my $node = $request->{node};
+    
+    # run the nodeset xx next
+    $subreq->({command=>['nodeset'], node=>$node, arg=>['next']}, $callback);
+
+    # run the 'updatenodestat <node> booted'
+    $subreq->({command=>['updatenodestat'], node=>$node, arg=>['booted']}, $callback);
+}
+
+# use the md5 to authorize the passwd
+sub authpw {
+    my $passwd = shift;
+
+    if ($passwd =~ /^\$1\$/) {
+        return $passwd;
+    } else {
+        my $cmd = "openssl passwd -1 $passwd";
+        return xCAT::Utils->runcmd($cmd, -1);
+    }
+}
+
+# Configure the network for host
+# create the network for cluster if it does not exist
+# configure the interface and add them to the corresponding network
+sub cfghypnw {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $host = shift;
+    my $interface = shift;
+    my $datacenter = shift;
+    
+    # the format of the interface attirbute
+    # networkname:interfacename:bootpro:IP:netmask:gateway
+    my @if = split(/\|/, $interface);
+    foreach (@if) {
+        my ($netname, $ifname, $bprotocol, $ip, $nm, $gw) = split (':', $_);
+        unless ($netname && $ifname) {
+            my $rsp;
+            push @{$rsp->{data}}, "$host: Missing network name or interface name: $_.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            next;
+        }
+
+        # get host id
+        my ($rc, $hostid, $stat) = search_src($ref_rhevm, "hosts", $host);
+        if ($rc) {
+            my $rsp;
+            push @{$rsp->{data}}, "$host: host was not created.";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            next;
+        }
+        
+        # get network interface and configure it
+        my $nicid;
+        my $api = "/api/hosts/$hostid/nics";
+        my $method = "GET";
+        my $request = genreq($ref_rhevm, $method, $api, "");
+        my $response;
+        ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+        if ($rc) {
+            my $rsp;
+            push @{$rsp->{data}}, "$host: $response";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            next;
+        } else {
+            my $parser = XML::LibXML->new();
+            my $doc = $parser->parse_string($response);
+            my @hostnics = $doc->findnodes("/host_nics/host_nic");
+            foreach my $nicnode (@hostnics) {
+                if ($ifname eq getAttr($nicnode, "name")) {
+                    $doc = $nicnode;
+                    last;
+                }
+            }
+                
+            if ($doc ) {
+                my $attr;
+                if ($attr = getAttr($doc, "", "id")) {
+                    $nicid = $attr;
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$host: does not have interface $ifname.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                }
+
+                # get the network
+                my $netid;
+                if ($attr = getAttr($doc, "network", "id")) {
+                    $netid = $attr;
+                }
+                
+                # check the bootprotocol and network parameters, and configure if needed
+                if (defined ($bprotocol) && $bprotocol =~ /^(dhcp|static)$/) {
+                    my $newpro;
+                    if ($attr = getAttr($doc, "boot_protocol")) {
+                        if ($attr eq "dhcp") {
+                            if ($bprotocol eq "static" ) {
+                                $newpro = "static";
+                            }
+                        } elsif ($attr eq "static") {
+                            if ($bprotocol eq "dhcp") {
+                                $newpro = "dhcp";
+                            } else {
+                                my ($curip, $curnm, $curgw);
+                                if ($attr = getAttr($doc, "ip", "address")) {
+                                    $curip = $attr;
+                                } 
+                                if ($attr = getAttr($doc, "ip", "netmask")) {
+                                    $curnm = $attr;
+                                } 
+                                if ($attr = getAttr($doc, "ip", "gateway")) {
+                                    $curgw = $attr;
+                                } 
+
+                                if ($ip ne $curip || $nm ne $curnm || $gw ne $curgw) {
+                                    $newpro = "static";
+                                }
+                            }
+                        }
+                    } else {
+                        $newpro = $bprotocol;
+                    }
+
+                    # Set the attributes for the nic
+                    $api = "/api/hosts/$hostid/nics/$nicid";
+                    $method = "PUT";
+                    my $content;
+                    if (defined ($newpro) && $newpro eq "dhcp")  {
+                        $content = "<host_nic><boot_protocol>dhcp</boot_protocol></host_nic>";
+                    } elsif (defined ($newpro) && $newpro eq "static")  {
+                        $content = "<host_nic><boot_protocol>static</boot_protocol><ip address=\"$ip\" netmask=\"$nm\" gateway=\"$gw\"/></host_nic>";
+                    }
+                    if (defined ($newpro)) {
+                        my $request = genreq($ref_rhevm, $method, $api, $content);
+                        ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+                        if ($rc) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$host: $response";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                        }
+                    }
+                } else {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$host: the boot procotol was not set or invalid.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                }
+
+                # search the network
+                my $curnetid;
+                ($rc, $curnetid, $stat) = search_src($ref_rhevm, "networks", $netname);
+                if ($rc) {
+                    if ($rc == 11) {
+                        my $rsp;
+                        push @{$rsp->{data}}, "$host: network: $netname does not exist.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    } else {
+                        my $rsp;
+                        push @{$rsp->{data}}, "$host: failed to get the network: $netname.";
+                        xCAT::MsgUtils->message("E", $rsp, $callback);
+                    }
+                    next;
+                }
+    
+                if ($netid eq $curnetid) {
+                    generalaction($callback, $ref_rhevm, "/api/hosts/$hostid/commitnetconfig");
+                    next;
+                }
+                if ($netid) {
+                    if ($netid eq $curnetid) { 
+                        next; 
+                    } else {
+                         #detach the interface to the network
+                         if (attach($callback, $ref_rhevm, "/api/hosts/$hostid/nics/$nicid", "network", $curnetid, 1)) {
+                            my $rsp;
+                            push @{$rsp->{data}}, "$host: failed to detach $ifname from $netname.";
+                            xCAT::MsgUtils->message("E", $rsp, $callback);
+                            next;
+                         }
+                    }
+                } 
+        
+                # attach the interface to the network
+                if (attach($callback, $ref_rhevm, "/api/hosts/$hostid/nics/$nicid", "network", $curnetid)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$host: failed to attach $ifname to $netname.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    next;
+                 }
+
+                 generalaction($callback, $ref_rhevm, "/api/hosts/$hostid/commitnetconfig");
+            }
+        }
+    }
+    
+    return 0;
+}
+
+# Create a Storage Domain
+# The parameters will be gotten from virtsd table
+sub mkSD {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $sd = shift;
+
+    # get the informage for the SD
+    my ($rc, $sdid, $state) = search_src($ref_rhevm, "storagedomains", $sd);
+    if (!$rc) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: storagedomains has been defined in the rhevm.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    } 
+
+    # get the attributes for the SD
+    my $vsdtab = xCAT::Table->new('virtsd',-create=>0);
+    my $vsdent = $vsdtab->getAttribs({'node'=>$sd}, ['sdtype', 'stype', 'location', 'host', 'datacenter']);
+    unless ($vsdent) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: cannot find the definition for $sd in the virtsd table.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    }
+
+    unless ($vsdent->{host}) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: a SPM host needs to be specified.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    }
+    unless ($vsdent->{stype} && $vsdent->{location}) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: the sdtype and location need to be specified.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    }
+
+    unless ($vsdent->{stype} =~ /^(nfs|localfs)$/) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: supported storage type: nfs, localfs.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    }
+
+    # get the host as SPM
+    my $hostid;
+    ($rc, $hostid, $state) = search_src($ref_rhevm, "hosts", $vsdent->{host});
+    if ($rc) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: cannot find the host $vsdent->{host}.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    } 
+    
+    # To create the SD
+    my $api = "/api/storagedomains";
+    my $method = "POST";
+
+    # Create the xml data
+    my $doc = XML::LibXML->createDocument();
+    my $root = $doc->createElement("storage_domain");
+    $doc->setDocumentElement($root);
+
+    $root->appendTextChild("name", $sd);
+
+    # set the host will be the SPM
+    my $host_ele = $doc->createElement("host");
+    $root->appendChild($host_ele);
+    $host_ele->setAttribute("id", $hostid);
+
+    # set the location of storage
+    my $storage_ele = $doc->createElement("storage");
+    $root->appendChild($storage_ele);
+    $storage_ele->appendTextChild("type", $vsdent->{stype});
+    
+    my ($address, $path) = split(':', $vsdent->{location});
+    if ($vsdent->{stype} eq "nfs") {
+        $storage_ele->appendTextChild("address", $address);
+        $storage_ele->appendTextChild("path", $path);
+    } elsif ($vsdent->{stype} eq "localfs") {
+        $storage_ele->appendTextChild("path", "/data/images/rhev");
+    }
+
+    if ($vsdent->{sdtype}) {
+        $root->appendTextChild("type", $vsdent->{sdtype});
+    } else {
+        $root->appendTextChild("type", "data");
+    }
+
+    my $request = genreq($ref_rhevm, $method, $api, $doc->toString);
+    my $response;
+    ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+
+    
+    if ($rc) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: $response";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 0;
+    } else {
+        my $parser = XML::LibXML->new();
+        my $doc = $parser->parse_string($response);
+        if ($doc ) {
+            my $sdid;
+            if ($sdid = getAttr($doc, "/storage_domain", "id")) {
+                if ($vsdent->{stype} eq "localfs") {
+                    #return directly
+                    return $sdid;
+                }
+                # attach the storage domain to the datacenter
+                my $dc = $vsdent->{datacenter};
+                unless ($dc) {$dc = "default"};
+                my $dcid;
+                ($rc, $dcid, $state) = search_src($ref_rhevm, "datacenters", $dc);
+                if ($rc) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$sd: $response";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    return 0;
+                }
+
+                # attach the storage domain to the datacenter
+                if (attach($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains", "storage_domain", $sdid)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$sd: failed to attach to datacenter:$dc.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    return 0;
+                }
+
+                # active the storage domain
+                if (activate($callback, $ref_rhevm,"/api/datacenters/$dcid/storagedomains/$sdid", $sd)) {
+                    my $rsp;
+                    push @{$rsp->{data}}, "$sd: failed to activate the storage domain.";
+                    xCAT::MsgUtils->message("E", $rsp, $callback);
+                    return 0;
+                }
+                
+                return $sdid;
+            }
+        }
+    }
+
+    return 0;
+}
+
+# Activate or Deactive a resource
+# 0 - suc; 1 - failed
+sub activate {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $path = shift;
+    my $name = shift;
+    my $deactivate = shift;
+
+    my $api;
+    if ($deactivate) {
+        $api = $path."/deactivate";
+    } else {
+        $api = $path."/activate";
+    }
+    my $method = "POST";
+    my $content = "<action/>";
+    my $request = genreq($ref_rhevm, $method, $api, $content);
+
+    my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+    if ($rc) {
+            my $rsp;
+            push @{$rsp->{data}}, "$name: $response";
+            xCAT::MsgUtils->message("E", $rsp, $callback);
+            return 1;
+    } else {
+        my $parser = XML::LibXML->new();
+        my $doc = $parser->parse_string($response);
+        if ($doc ) {
+            my $attr;
+            if ($attr = getAttr($doc, "/action/status/state")) {
+                if ($attr ne "complete") {
+                    if (waitforcomplte()) {
+                        return 1;
+                    } else {
+                        return 0;
+                    }
+                } else {
+                    return 0;
+                }
+            }
+        }
+    }
+    return 1;
+}
+
+# Attach or Detach a resource
+# type: network (for host nic), storage_domain (for sd)
+# 0 - suc; 1 - failed
+sub attach {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $path = shift;
+    my $type = shift;
+    my $id = shift;
+    my $detach = shift;
+
+    my $method = "POST";
+    my $api;
+    my $content;
+    if ($type eq "storage_domain") {
+        if ($detach) {
+            $api = "$path/$id";
+            $method = "DELETE";
+            $content = "";
+        } else {
+            $api = $path;
+            $content = "<$type id=\"$id\"/>";
+        }
+    } else {
+        if ($detach) {
+            $api = $path."/detach";
+        } else {
+            $api = $path."/attach";
+        }
+        $content = "<action><$type id=\"$id\"/></action>";
+    }
+    
+    
+    my $request = genreq($ref_rhevm, $method, $api, $content);
+
+    my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+    if ($rc) {
+        # no output for detaching sd from datacenter
+        if ($rc == 2 && $type eq "storage_domain" && $detach) {
+            return 0;
+        }
+        my $rsp;
+        push @{$rsp->{data}}, "$response:$rc";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    } else {
+        my $parser = XML::LibXML->new();
+        my $doc = $parser->parse_string($response);
+        if ($doc ) {
+            my $attr;
+            if ($type eq "storage_domain") {
+                 if ("inactive" eq getAttr($doc, "/storage_domain/status/state")) {
+                     return 0;
+                 } else {
+                     return 1;
+                 }
+            } else {
+                if ("complete" eq getAttr($doc, "/action/status/state")) {
+                    return 0;
+                 } else {
+                    return 1;
+                }
+            }
+        }
+    }
+    return 1;
+}
+
+# Common subroutine for general action of rest api
+sub generalaction {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $api = shift;
+    my $method = shift;
+    my $norsp = shift;
+    my $force = shift;
+
+    unless ($method) {
+        $method = "POST";
+    }
+
+    my $content = "<action/>";
+    if ($force) {
+        $content = "<action><force>true</force></action>";
+    }
+    my $request = genreq($ref_rhevm, $method, $api, $content);
+    my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+
+    # no need to handle response for DELETE
+    if ($norsp) {
+        return;
+    }
+    
+    if ($rc) {
+        my $rsp;
+        push @{$rsp->{data}}, "$response";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    }
+}
+
+# delete storage domain
+sub deleteSD {
+    my $callback = shift;
+    my $ref_rhevm = shift;
+    my $path = shift;
+    my $sd = shift;
+
+    # get the attributes for the SD
+    my $vsdtab = xCAT::Table->new('virtsd',-create=>0);
+    my $vsdent = $vsdtab->getAttribs({'node'=>$sd}, ['host']);
+    unless ($vsdent) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: cannot find the definition for $sd in the virtsd table.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    }
+
+    unless ($vsdent->{host}) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: a SPM host needs to be specified.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    }
+    
+    # get the id of host
+    my ($rc, $hostid, $stat) = search_src($ref_rhevm, "hosts", $vsdent->{host});
+    if ($rc) {
+        my $rsp;
+        push @{$rsp->{data}}, "$sd: Cannot find the host: $vsdent->{host} for the storag domain.";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    }
+    
+    my $method = "DELETE";
+    my $api = $path;
+    my $content;
+
+    $content = "<storage_domain><host id=\"$hostid\"/><format>true</format></storage_domain>";
+
+    my $request = genreq($ref_rhevm, $method, $api, $content);
+    my $response;
+    ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+
+    # no need to handle response for DELETE
+    if ($rc) {
+        # no output for detaching sd from datacenter
+        if ($rc == 2) {
+            return 0;
+        }
+        my $rsp;
+        push @{$rsp->{data}}, "$response";
+        xCAT::MsgUtils->message("E", $rsp, $callback);
+        return 1;
+    }
+}
+
+sub waitforcomplete {
+    my $ref_rhevm = shift;
+    my $api = shift;
+    my $criteria = shift;
+    my $timeout = shift;
+
+    unless ($timeout) {
+        $timeout = 10;
+    }
+
+    my ($path, $target) = split ('=', $criteria);
+
+    my $method = "GET";
+    my $content = "";
+
+    my $start = Time::HiRes::gettimeofday();
+
+    while (1) {
+
+        my $request = genreq($ref_rhevm, $method, $api, $content);
+        my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+    
+        if ($rc) {
+            return ($rc, $response);
+        } else {
+            my $parser = XML::LibXML->new();
+            my $doc = $parser->parse_string($response);
+            if ($doc ) {
+                if ($target eq getAttr($doc, $path)) {
+                    return 0;
+                }
+            }
+        }
+
+        my $now = Time::HiRes::gettimeofday();
+        if (($now - $start) > $timeout) {
+            return 2;
+        } else {
+            sleep (0.5);
+        }
+    }
+    
+    return 1;
+}
+
+# Get the vid prameters for external video console program to display console
+sub getrvidparms {
+    my $callback = shift;
+    my $rhevm_hash = shift;
+    my $nodes = shift;
+
+    foreach my $rhevm (keys %{$rhevm_hash}) {
+        my @nodes;
+        # generate the hash of rhevm which will be used for the action functions
+        my $ref_rhevm = {'name' => $rhevm, 
+                                 'user' => $rhevm_hash->{$rhevm}->{user}, 
+                                 'pw' => $rhevm_hash->{$rhevm}->{pw}};
+
+        # generate the node that will be handled
+        if (defined $rhevm_hash->{$rhevm}->{host}) {
+            foreach my $rhevh (keys %{$rhevm_hash->{$rhevm}->{host}}) {
+                if (defined $rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}) {
+                    push @nodes, @{$rhevm_hash->{$rhevm}->{host}->{$rhevh}->{node}};
+                }
+            }
+        } elsif (defined $rhevm_hash->{$rhevm}->{node}) {
+             push @nodes, @{$rhevm_hash->{$rhevm}->{node}};
+        }
+
+        # perform the action against the node
+        foreach my $node (@nodes) {
+            my $node = $nodes->[0];
+            my %consparam;
+            $consparam{method} = 'kvm';
+        
+            # get the attributes for vm
+            my $api = "/api/vms?search=$node";
+            my $method = "GET";
+            my $content = "";
+        
+            my $request = genreq($ref_rhevm, $method, $api, $content);
+            my ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+        
+            my $vmid;
+            my $rsp;
+            if ($rc) {
+                $rsp->{node}->[0]->{errorcode} = $rc;
+                $rsp->{node}->[0]->{name}->[0]=$node;
+                $rsp->{node}->[0]->{error} = $response;
+                $callback->($rsp);
+                next;
+            } else {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                if ($doc ) {
+                    my $attr;
+                    if ($attr = getAttr($doc, "/vms/vm", "id")) {
+                        $vmid = $attr;
+                    }
+                    if ($attr = getAttr($doc, "/vms/vm/display/type")) {
+                        $consparam{vidproto} = $attr;
+                    }
+                    if ($attr = getAttr($doc, "/vms/vm/display/address")) {
+                        $consparam{server} = $attr;
+                    }
+                    if ($attr = getAttr($doc, "/vms/vm/display/port")) {
+                        $consparam{vidport} = $attr;
+                    }
+                }
+            }
+        
+            # get the password ticket for the external program to accesss the VNC
+            $api = "/api/vms/$vmid/ticket";
+            $method = "POST";
+            $content = "<action><ticket><expiry>120</expiry></ticket></action>";
+        
+            $request = genreq($ref_rhevm, $method, $api, $content);
+            ($rc, $response) = send_req($ref_rhevm, $request->as_string());
+        
+            if ($rc) {
+                $rsp->{node}->[0]->{errorcode} = $rc;
+                $rsp->{node}->[0]->{name}->[0]=$node;
+                $rsp->{node}->[0]->{error} = $response;
+                $callback->($rsp);
+                next;
+            } else {
+                my $parser = XML::LibXML->new();
+                my $doc = $parser->parse_string($response);
+                if ($doc ) {
+                    my $attr;
+                    if ($attr = getAttr($doc, "/action/ticket/value")) {
+                        $consparam{password} = $attr;
+                    }    
+                }
+            }
+        
+            
+            $rsp = ();
+            $rsp->{node}->[0]->{name}->[0]=$node;
+            foreach (keys %consparam) {
+                $rsp->{node}->[0]->{data}->[0]->{desc}->[0] = $_;
+                $rsp->{node}->[0]->{data}->[0]->{contents}->[0] = $consparam{$_};
+                $callback->($rsp);
+            }
+        }
+    }
+
+    return;
+}
+
+
+1;    
diff --git a/xCAT-server/xCAT-wsapi/xcatrhevh.cgi b/xCAT-server/xCAT-wsapi/xcatrhevh.cgi
new file mode 100644
index 000000000..d56811288
--- /dev/null
+++ b/xCAT-server/xCAT-wsapi/xcatrhevh.cgi
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+
+# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
+
+use strict;
+use CGI qw/:standard/;
+use Socket;
+use IO::Socket::INET;
+use IO::Socket::SSL; IO::Socket::SSL->import('inet4');
+
+
+my $q           = CGI->new;
+my $url         = $q->url;
+my $pathInfo    = $q->path_info;
+my $peerAdd	= $q->remote_addr;
+
+my $iaddr = inet_aton($peerAdd);
+my $peerhost	= gethostbyaddr($iaddr, AF_INET);
+$peerhost =~ s/\..*//;
+
+if ($pathInfo =~ /^\/rhevh_finish_install\/(.*)$/) {
+  if ($1 eq $peerhost) {
+    &rhevhupdateflag($peerhost);
+    my $cmd = "rhevhupdateflag"; 
+  }    
+}
+# check mapping of the IP and hostname
+
+sub rhevhupdateflag {
+  my $node = shift;
+
+
+  my $socket = IO::Socket::INET->new(
+    PeerAddr => "127.0.0.1",
+    PeerPort => '3001',
+    Timeout => 15,);
+  my $client;
+  if ($socket) {
+    $client =  IO::Socket::SSL->start_SSL($socket,
+		 Timeout => 0,
+		);
+  }
+
+  my $req1 = "<xcatrequest><command>rhevhupdateflag</command><noderange>";
+  my $req2 = "</noderange></xcatrequest>";
+  my $req = $req1.$node.$req2;
+
+  print $client $req;
+}
+