diff --git a/include/History.h b/include/History.h index 35e38a3569..0f46fc86f2 100644 --- a/include/History.h +++ b/include/History.h @@ -46,6 +46,7 @@ public: const string& hostname, const string& vm_dir, const string& vmm, + const string& vnm, const string& tm); ~History(){}; @@ -91,6 +92,7 @@ private: int hid; string vmm_mad_name; + string vnm_mad_name; string tm_mad_name; time_t stime; diff --git a/include/Host.h b/include/Host.h index f112532aa0..cb9403cdf4 100644 --- a/include/Host.h +++ b/include/Host.h @@ -130,6 +130,15 @@ public: return vmm_mad_name; }; + /** + * Retrives VNM mad name + * @return string vnm mad name + */ + const string& get_vnm_mad() const + { + return vnm_mad_name; + }; + /** * Retrives TM mad name * @return string tm mad name @@ -311,6 +320,11 @@ private: */ string vmm_mad_name; + /** + * Name of the VN driver used to manage networking in this host + */ + string vnm_mad_name; + /** * Name of the TM driver used to transfer file to and from this host */ @@ -338,6 +352,7 @@ private: const string& hostname="", const string& im_mad_name="", const string& vmm_mad_name="", + const string& vnm_mad_name="", const string& tm_mad_name=""); virtual ~Host(); diff --git a/include/HostPool.h b/include/HostPool.h index 89a516218e..50686a60fe 100644 --- a/include/HostPool.h +++ b/include/HostPool.h @@ -51,6 +51,7 @@ public: const string& hostname, const string& im_mad_name, const string& vmm_mad_name, + const string& vnm_mad_name, const string& tm_mad_name, string& error_str); diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index 6f357b23e7..4aa66c4235 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -259,9 +259,9 @@ public: * Generates a XML string for the template of the Object * @param xml the string to store the XML description. */ - void template_to_xml(string &xml) const + string& template_to_xml(string &xml) const { - obj_template->to_xml(xml); + return obj_template->to_xml(xml); } /** diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index ea70ad35f5..8c2dcccf32 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -51,13 +51,14 @@ protected: bool vm_authorization(int id, int hid, ImageTemplate *tmpl, RequestAttributes& att); - int get_host_information(int hid, string& name, string& vmm, string& tm, - RequestAttributes& att); + int get_host_information(int hid, string& name, string& vmm, string& vnm, + string& tm, RequestAttributes& att); int add_history(VirtualMachine * vm, int hid, const string& hostname, const string& vmm_mad, + const string& vnm_mad, const string& tm_mad, RequestAttributes& att); @@ -107,12 +108,9 @@ class VirtualMachineMigrate : public RequestManagerVirtualMachine { public: VirtualMachineMigrate(): - RequestManagerVirtualMachine("VirtualMachineDeploy", + RequestManagerVirtualMachine("VirtualMachineMigrate", "Migrates a virtual machine", - "A:siib") - { - auth_op = AuthRequest::DEPLOY; - }; + "A:siib"){}; ~VirtualMachineMigrate(){}; diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 568c48ceee..a375b97242 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -217,6 +217,7 @@ public: const string& hostname, const string& vm_dir, const string& vmm_mad, + const string& vnm_mad, const string& tm_mad); /** @@ -273,6 +274,26 @@ public: return previous_history->vmm_mad_name; }; + /** + * Returns the VNM driver name for the current host. The hasHistory() + * function MUST be called before this one. + * @return the VNM mad name + */ + const string & get_vnm_mad() const + { + return history->vnm_mad_name; + }; + + /** + * Returns the VNM driver name for the previous host. The hasPreviousHistory() + * function MUST be called before this one. + * @return the VNM mad name + */ + const string & get_previous_vnm_mad() const + { + return previous_history->vnm_mad_name; + }; + /** * Returns the TM driver name for the current host. The hasHistory() * function MUST be called before this one. diff --git a/include/VirtualMachineManager.h b/include/VirtualMachineManager.h index 03fea34a94..cab1799800 100644 --- a/include/VirtualMachineManager.h +++ b/include/VirtualMachineManager.h @@ -175,6 +175,41 @@ private: const string & action, void * arg); + /** + * Function to format a VMM Driver message in the form: + * + * hostname + * net_drv + * m_hostname + * m_net_drv + * domain_id + * dfile + * cfile + * + * VM representation in XML + * + * + * + * @param hostname of the host to perform the action + * @param net_drv name of the vlan driver + * @param m_hostname name of the host to migrate the VM + * @param m_net_drv name of the vlan driver + * @param domain domain id as returned by the hypervisor + * @param dfile deployment file to boot the VM + * @param cfile checkpoint file to save the VM + * @param tmpl the VM information in XML + */ + string * format_message( + const string& hostname, + const string& net_drv, + const string& m_hostname, + const string& m_net_drv, + const string& domain, + const string& ldfile, + const string& rdfile, + const string& cfile, + const string& tmpl); + /** * Function executed when a DEPLOY action is received. It deploys a VM on * a Host. diff --git a/include/VirtualMachineManagerDriver.h b/include/VirtualMachineManagerDriver.h index a1f219e4e3..2d75485ed4 100644 --- a/include/VirtualMachineManagerDriver.h +++ b/include/VirtualMachineManagerDriver.h @@ -110,108 +110,76 @@ private: friend class VirtualMachineManager; /** - * Sends a deploy request to the MAD: "DEPLOY ID HOST CONF -" + * Sends a deploy request to the MAD: "DEPLOY ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param conf the filename of the deployment file + * @param drv_msg xml data for the mad operation */ void deploy ( const int oid, - const string& host, - const string& conf) const; + const string& drv_msg) const; /** - * Sends a shutdown request to the MAD: "SHUTDOWN ID HOST NAME -" + * Sends a shutdown request to the MAD: "SHUTDOWN ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver + * @param drv_msg xml data for the mad operation */ void shutdown ( const int oid, - const string& host, - const string& name) const; + const string& drv_msg) const; /** - * Sends a cancel request to the MAD: "CANCEL ID HOST NAME -" + * Sends a cancel request to the MAD: "CANCEL ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver + * @param drv_msg xml data for the mad operation */ void cancel ( const int oid, - const string& host, - const string& name) const; + const string& drv_msg) const; /** - * Sends a checkpoint request to the MAD: "CHECKPOINT ID HOST NAME FILE" + * Sends a checkpoint request to the MAD: "CHECKPOINT ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver - * @param file the filename to generate the checkpoint file + * @param drv_msg xml data for the mad operation */ void checkpoint ( const int oid, - const string& host, - const string& name, - const string& file) const; + const string& drv_msg) const; /** - * Sends a save request to the MAD: "SAVE ID HOST NAME FILE" + * Sends a save request to the MAD: "SAVE ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver - * @param file the filename to generate the checkpoint file + * @param drv_msg xml data for the mad operation */ void save ( const int oid, - const string& host, - const string& name, - const string& file) const; + const string& drv_msg) const; /** - * Sends a save request to the MAD: "RESTORE ID HOST FILE -" + * Sends a save request to the MAD: "RESTORE ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver - * @param file the filename of the checkpoint file to restore the VM - * from + * @param drv_msg xml data for the mad operation */ void restore ( const int oid, - const string& host, - const string& name, - const string& file) const; + const string& drv_msg) const; /** - * Sends a migrate request to the MAD: "MIGRATE ID HOST NAME DEST" + * Sends a migrate request to the MAD: "MIGRATE ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param shost the original host (source) - * @param name of the Virtual Machine (deployment id), as returned by the - * driver - * @param dhost the destination host + * @param drv_msg xml data for the mad operation */ void migrate ( const int oid, - const string& shost, - const string& name, - const string& dhost) const; + const string& drv_msg) const; /** - * Sends a poll request to the MAD: "POLL ID HOST NAME -" + * Sends a poll request to the MAD: "POLL ID XML_DRV_MSG" * @param oid the virtual machine id. - * @param host the hostname - * @param name of the Virtual Machine (deployment id), as returned by the - * driver + * @param drv_msg xml data for the mad operation */ void poll ( const int oid, - const string& host, - const string& name) const; + const string& drv_msg) const; }; /* -------------------------------------------------------------------------- */ diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index be02e86954..b398b8aee2 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -208,6 +208,11 @@ private: */ string vlan_id; + /** + * Whether or not to isolate this network with the vnm driver + */ + int vlan; + // ------------------------------------------------------------------------- // Virtual Network Description // ------------------------------------------------------------------------- diff --git a/install.sh b/install.sh index a8ded00a12..6fb7f2bcfe 100755 --- a/install.sh +++ b/install.sh @@ -122,9 +122,9 @@ if [ -z "$ROOT" ] ; then elif [ "$OZONES" = "yes" ]; then MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $VAR_LOCATION $OZONES_LOCATION \ $ETC_LOCATION" - + DELETE_DIRS="$MAKE_DIRS" - + CHOWN_DIRS="" else MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $ETC_LOCATION $VAR_LOCATION \ @@ -162,8 +162,8 @@ else elif [ "$OZONES" = "yes" ]; then MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $VAR_LOCATION $OZONES_LOCATION \ $ETC_LOCATION" - - DELETE_DIRS="$MAKE_DIRS" + + DELETE_DIRS="$MAKE_DIRS" else MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $ETC_LOCATION $VAR_LOCATION \ $INCLUDE_LOCATION $SHARE_LOCATION $IMAGES_LOCATION \ @@ -223,10 +223,15 @@ VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/im/vmware.d \ $VAR_LOCATION/remotes/im/ganglia.d \ $VAR_LOCATION/remotes/vmm/kvm \ + $VAR_LOCATION/remotes/vnm \ + $VAR_LOCATION/remotes/vnm/802.1Q \ + $VAR_LOCATION/remotes/vnm/dummy \ + $VAR_LOCATION/remotes/vnm/ebtables \ + $VAR_LOCATION/remotes/vnm/fw \ + $VAR_LOCATION/remotes/vnm/ovswitch \ $VAR_LOCATION/remotes/vmm/xen \ $VAR_LOCATION/remotes/vmm/vmware \ $VAR_LOCATION/remotes/hooks \ - $VAR_LOCATION/remotes/hooks/vnm \ $VAR_LOCATION/remotes/hooks/ft \ $VAR_LOCATION/remotes/image \ $VAR_LOCATION/remotes/image/fs \ @@ -258,7 +263,7 @@ SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \ $SUNSTONE_LOCATION/public/images \ $SUNSTONE_LOCATION/templates \ $SUNSTONE_LOCATION/views" - + OZONES_DIRS="$OZONES_LOCATION/lib \ $OZONES_LOCATION/lib/OZones \ $OZONES_LOCATION/models \ @@ -340,8 +345,8 @@ INSTALL_FILES=( AUTH_SERVER_X509_FILES:$VAR_LOCATION/remotes/auth/server_x509 AUTH_SERVER_CIPHER_FILES:$VAR_LOCATION/remotes/auth/server_cipher AUTH_DUMMY_FILES:$VAR_LOCATION/remotes/auth/dummy - AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain - AUTH_QUOTA_FILES:$VAR_LOCATION/remotes/auth/quota + AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain + AUTH_QUOTA_FILES:$VAR_LOCATION/remotes/auth/quota VMM_EXEC_KVM_SCRIPTS:$VAR_LOCATION/remotes/vmm/kvm VMM_EXEC_XEN_SCRIPTS:$VAR_LOCATION/remotes/vmm/xen VMM_EXEC_VMWARE_SCRIPTS:$VAR_LOCATION/remotes/vmm/vmware @@ -351,13 +356,17 @@ INSTALL_FILES=( DUMMY_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/dummy LVM_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/lvm IMAGE_DRIVER_FS_SCRIPTS:$VAR_LOCATION/remotes/image/fs - NETWORK_HOOK_SCRIPTS:$VAR_LOCATION/remotes/vnm + NETWORK_FILES:$VAR_LOCATION/remotes/vnm + NETWORK_8021Q_FILES:$VAR_LOCATION/remotes/vnm/802.1Q + NETWORK_DUMMY_FILES:$VAR_LOCATION/remotes/vnm/dummy + NETWORK_EBTABLES_FILES:$VAR_LOCATION/remotes/vnm/ebtables + NETWORK_FW_FILES:$VAR_LOCATION/remotes/vnm/fw + NETWORK_OVSWITCH_FILES:$VAR_LOCATION/remotes/vnm/ovswitch EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples INSTALL_NOVNC_SHARE_FILE:$SHARE_LOCATION INSTALL_GEMS_SHARE_FILE:$SHARE_LOCATION TM_EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples/tm HOOK_FT_FILES:$VAR_LOCATION/remotes/hooks/ft - HOOK_NETWORK_FILES:$VAR_LOCATION/remotes/hooks/vnm COMMON_CLOUD_LIB_FILES:$LIB_LOCATION/ruby/cloud CLOUD_AUTH_LIB_FILES:$LIB_LOCATION/ruby/cloud/CloudAuth ECO_LIB_FILES:$LIB_LOCATION/ruby/cloud/econe @@ -513,6 +522,9 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \ src/mad/ruby/CommandManager.rb \ src/mad/ruby/OpenNebulaDriver.rb \ src/mad/ruby/VirtualMachineDriver.rb \ + src/mad/ruby/DriverExecHelper.rb \ + src/mad/ruby/ssh_stream.rb \ + src/vnm_mad/one_vnm.rb \ src/mad/ruby/Ganglia.rb \ src/mad/ruby/vmwarelib.rb \ src/oca/ruby/OpenNebula.rb \ @@ -645,6 +657,38 @@ AUTH_PLAIN_FILES="src/authm_mad/remotes/plain/authenticate" AUTH_QUOTA_FILES="src/authm_mad/remotes/quota/authorize" +#------------------------------------------------------------------------------- +# Virtual Network Manager drivers to be installed under $REMOTES_LOCATION/vnm +#------------------------------------------------------------------------------- + +NETWORK_FILES="src/vnm_mad/remotes/OpenNebulaNetwork.rb \ + src/vnm_mad/remotes/Firewall.rb \ + src/vnm_mad/remotes/OpenNebulaNic.rb" + +NETWORK_8021Q_FILES="src/vnm_mad/remotes/802.1Q/clean \ + src/vnm_mad/remotes/802.1Q/post \ + src/vnm_mad/remotes/802.1Q/pre \ + src/vnm_mad/remotes/802.1Q/HostManaged.rb" + +NETWORK_DUMMY_FILES="src/vnm_mad/remotes/dummy/clean \ + src/vnm_mad/remotes/dummy/post \ + src/vnm_mad/remotes/dummy/pre" + +NETWORK_EBTABLES_FILES="src/vnm_mad/remotes/ebtables/clean \ + src/vnm_mad/remotes/ebtables/post \ + src/vnm_mad/remotes/ebtables/pre \ + src/vnm_mad/remotes/ebtables/Ebtables.rb" + +NETWORK_FW_FILES="src/vnm_mad/remotes/fw/post \ + src/vnm_mad/remotes/fw/pre \ + src/vnm_mad/remotes/fw/clean" + +NETWORK_OVSWITCH_FILES="src/vnm_mad/remotes/ovswitch/clean \ + src/vnm_mad/remotes/ovswitch/post \ + src/vnm_mad/remotes/ovswitch/pre \ + src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb" + + #------------------------------------------------------------------------------- # Transfer Manager commands, to be installed under $LIB_LOCATION/tm_commands # - SHARED TM, $LIB_LOCATION/tm_commands/shared @@ -800,20 +844,9 @@ TM_EXAMPLE_SHARE_FILES="share/examples/tm/tm_clone.sh \ HOOK_FT_FILES="share/hooks/host_error.rb" #------------------------------------------------------------------------------- -# Network Hook scripts, to be installed under $VAR_LOCATION/remotes/hooks +# Installation scripts, to be installed under $SHARE_LOCATION #------------------------------------------------------------------------------- -HOOK_NETWORK_FILES="src/vnm_mad/hm-vlan \ - src/vnm_mad/ebtables-vlan \ - src/vnm_mad/firewall \ - src/vnm_mad/HostManaged.rb \ - src/vnm_mad/OpenNebulaNetwork.rb \ - src/vnm_mad/OpenNebulaNic.rb \ - src/vnm_mad/OpenvSwitch.rb \ - src/vnm_mad/openvswitch-vlan \ - src/vnm_mad/Firewall.rb \ - src/vnm_mad/Ebtables.rb" - INSTALL_NOVNC_SHARE_FILE="share/install_novnc.sh" INSTALL_GEMS_SHARE_FILE="share/install_gems/install_gems" @@ -1080,7 +1113,7 @@ SUNSTONE_PUBLIC_IMAGES_FILES="src/sunstone/public/images/ajax-loader.gif \ src/sunstone/public/images/Refresh-icon.png \ src/sunstone/public/images/vnc_off.png \ src/sunstone/public/images/vnc_on.png" - + #----------------------------------------------------------------------------- # Ozones files #----------------------------------------------------------------------------- @@ -1095,10 +1128,10 @@ OZONES_ETC_FILES="src/ozones/Server/etc/ozones-server.conf" OZONES_MODELS_FILES="src/ozones/Server/models/OzonesServer.rb \ src/ozones/Server/models/Auth.rb \ src/sunstone/models/OpenNebulaJSON/JSONUtils.rb" - + OZONES_TEMPLATE_FILES="src/ozones/Server/templates/index.html \ src/ozones/Server/templates/login.html" - + OZONES_LIB_FILES="src/ozones/Server/lib/OZones.rb" OZONES_LIB_ZONE_FILES="src/ozones/Server/lib/OZones/Zones.rb \ @@ -1112,7 +1145,7 @@ OZONES_LIB_ZONE_FILES="src/ozones/Server/lib/OZones/Zones.rb \ src/ozones/Server/lib/OZones/AggregatedPool.rb \ src/ozones/Server/lib/OZones/AggregatedImages.rb \ src/ozones/Server/lib/OZones/AggregatedTemplates.rb" - + OZONES_LIB_API_FILES="src/ozones/Client/lib/zona.rb" OZONES_LIB_API_ZONA_FILES="src/ozones/Client/lib/zona/ZoneElement.rb \ @@ -1124,7 +1157,7 @@ OZONES_LIB_API_ZONA_FILES="src/ozones/Client/lib/zona/ZoneElement.rb \ src/ozones/Client/lib/zona/ZonePool.rb" OZONES_PUBLIC_VENDOR_JQUERY=$SUNSTONE_PUBLIC_VENDOR_JQUERY - + OZONES_PUBLIC_VENDOR_DATATABLES=$SUNSTONE_PUBLIC_VENDOR_DATATABLES OZONES_PUBLIC_VENDOR_JGROWL=$SUNSTONE_PUBLIC_VENDOR_JGROWL @@ -1134,18 +1167,18 @@ OZONES_PUBLIC_VENDOR_JQUERYUI=$SUNSTONE_PUBLIC_VENDOR_JQUERYUI OZONES_PUBLIC_VENDOR_JQUERYUIIMAGES=$SUNSTONE_PUBLIC_VENDOR_JQUERYUIIMAGES OZONES_PUBLIC_VENDOR_JQUERYLAYOUT=$SUNSTONE_PUBLIC_VENDOR_JQUERYLAYOUT - + OZONES_PUBLIC_JS_FILES="src/ozones/Server/public/js/ozones.js \ src/ozones/Server/public/js/login.js \ src/ozones/Server/public/js/ozones-util.js \ src/sunstone/public/js/layout.js \ src/sunstone/public/js/sunstone.js \ src/sunstone/public/js/sunstone-util.js" - + OZONES_PUBLIC_CSS_FILES="src/ozones/Server/public/css/application.css \ src/ozones/Server/public/css/layout.css \ src/ozones/Server/public/css/login.css" - + OZONES_PUBLIC_IMAGES_FILES="src/ozones/Server/public/images/panel.png \ src/ozones/Server/public/images/login.png \ src/ozones/Server/public/images/login_over.png \ @@ -1159,16 +1192,16 @@ OZONES_PUBLIC_JS_PLUGINS_FILES="src/ozones/Server/public/js/plugins/zones-tab.js src/ozones/Server/public/js/plugins/vdcs-tab.js \ src/ozones/Server/public/js/plugins/aggregated-tab.js \ src/ozones/Server/public/js/plugins/dashboard-tab.js" - -OZONES_LIB_CLIENT_CLI_FILES="src/ozones/Client/lib/cli/ozones_helper.rb" - + +OZONES_LIB_CLIENT_CLI_FILES="src/ozones/Client/lib/cli/ozones_helper.rb" + OZONES_LIB_CLIENT_CLI_HELPER_FILES="\ src/ozones/Client/lib/cli/ozones_helper/vdc_helper.rb \ - src/ozones/Client/lib/cli/ozones_helper/zones_helper.rb" + src/ozones/Client/lib/cli/ozones_helper/zones_helper.rb" OZONES_BIN_CLIENT_FILES="src/ozones/Client/bin/onevdc \ src/ozones/Client/bin/onezone" - + OZONES_RUBY_LIB_FILES="src/oca/ruby/OpenNebula.rb" #----------------------------------------------------------------------------- @@ -1246,7 +1279,7 @@ if [ "$CLIENT" = "yes" ]; then elif [ "$SUNSTONE" = "yes" ]; then INSTALL_SET="${INSTALL_SUNSTONE_RUBY_FILES[@]} ${INSTALL_SUNSTONE_FILES[@]}" elif [ "$OZONES" = "yes" ]; then - INSTALL_SET="${INSTALL_OZONES_RUBY_FILES[@]} ${INSTALL_OZONES_FILES[@]}" + INSTALL_SET="${INSTALL_OZONES_RUBY_FILES[@]} ${INSTALL_OZONES_FILES[@]}" else INSTALL_SET="${INSTALL_FILES[@]} ${INSTALL_OZONES_FILES[@]} \ ${INSTALL_SUNSTONE_FILES[@]}" diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 2055202425..65cfb004d3 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -438,136 +438,6 @@ HM_MAD = [ # arguments = "$VMID" ] #------------------------------------------------------------------------------- -#******************************************************************************* -# Networking Hooks -#******************************************************************************* -# The following network hooks can be activated in order to manage network -# isolation and firewalls. -#******************************************************************************* -#------------------------------------------------------------------------------- -# Firewall -#------------------------------------------------------------------------------- -# -# Firewalling rules activated in the physical host executing the VM. Can be used -# to filter TCP and UDP ports, and to define a policy for ICMP connections. To -# use it specify under the NIC section of the VM one or more of the following -# attributes: -# -# - WHITE_PORTS_TCP = iptables_range -# Permits access to the VM only through the specified ports in the TCP -# protocol. Supersedes BLACK_PORTS_TCP if defined. -# -# - BLACK_PORTS_TCP = iptables_range -# Doesn't permit access to the VM through the specified ports in the TCP -# protocol. Superseded by WHITE_PORTS_TCP if defined. -# -# - WHITE_PORTS_UDP = iptables_range -# Permits access to the VM only through the specified ports in the UDP -# protocol. Supersedes BLACK_PORTS_UDP if defined. -# -# - BLACK_PORTS_UDP = iptables_range -# Doesn't permit access to the VM through the specified ports in the UDP -# protocol. Superseded by WHITE_PORTS_UDP if defined. -# -# - ICMP = no | drop -# Blocks ICMP connections to the VM. By default it's enabled. -# -# This hook requires the sudoers file to be configured so oneadmin can execute -# iptables without a password. -# -#------------------------------------------------------------------------------- -# -# VM_HOOK = [ -# name = "firewall-on", -# on = "RUNNING", -# command = "vnm/firewall", -# arguments = "on $TEMPLATE", -# remote = "yes" ] -# -# VM_HOOK = [ -# name = "firewall-off", -# on = "DONE", -# command = "vnm/firewall", -# arguments = "off $TEMPLATE", -# remote = "yes" ] -#------------------------------------------------------------------------------- -# Host-managed VLANs -#------------------------------------------------------------------------------- -# -# Network isolation provided through host-managed vlans. This hook will create a -# bridge for each OpenNebula virtual network and attach a tagged network -# interface to the bridge. -# -# For this hook to be effective you need to specify the attribute PHYDEV in your -# VNET template, which should contain the name of the physical network interface -# each VM should be attached to. If BRIDGE is not defined it will be -# automatically generated. -# -# In order to use this hook you need to: -# - load module 8021q -# - install vconfig -# - configure passwordless sudo in the worker nodes for oneadmin for these -# commands: brctl, ip, vconfig. -# -#------------------------------------------------------------------------------- -# -# VM_HOOK = [ -# name = "hm-vlan", -# on = "PROLOG", -# command = "vnm/hm-vlan", -# arguments = "$TEMPLATE", -# remote = "yes" ] -# -#------------------------------------------------------------------------------- -# Ebtables Network Isolation -#------------------------------------------------------------------------------- -# -# Network isolation provided through ebtables rules applied on the bridges. This -# method will only permit isolation with a mask of 255.255.255.0. -# -# This hook requires the sudoers file to be configured so oneadmin can execute -# ebtables without a password, and the ebtables package to be installed. -# -#------------------------------------------------------------------------------- -# -# VM_HOOK = [ -# name = "ebtables-vlan-on", -# on = "RUNNING", -# command = "vnm/ebtables-vlan", -# arguments = "on $TEMPLATE", -# remote = "yes" ] -# -# VM_HOOK = [ -# name = "ebtables-vlan-off", -# on = "DONE", -# command = "vnm/ebtables-vlan", -# arguments = "off $TEMPLATE", -# remote = "yes" ] -# -#------------------------------------------------------------------------------- -# Open vSwitch Network Isolation -#------------------------------------------------------------------------------- -# -# Network isolation provided through Open vSwitch. Each virtual network -# interface will receive an VLAN tag enabling network isolation. -# -# This hook requires Open vSwitch to be installed along with the Open vSwitch -# compatibility layer for Linux bridging, on each worker node. -# See http://openvswitch.org/ for more information. -# -# Passwordless sudo permissions for oneadmin to execute ovs_vsctl. -# -#------------------------------------------------------------------------------- -# -# VM_HOOK = [ -# name = "openvswitch-vlan", -# on = "RUNNING", -# command = "vnm/openvswitch-vlan", -# arguments = "$TEMPLATE", -# remote = "yes" ] -# -#------------------------------------------------------------------------------- - #******************************************************************************* # Auth Manager Configuration #******************************************************************************* diff --git a/src/authm_mad/one_auth_mad.rb b/src/authm_mad/one_auth_mad.rb index 46d8136344..245c660944 100755 --- a/src/authm_mad/one_auth_mad.rb +++ b/src/authm_mad/one_auth_mad.rb @@ -111,7 +111,8 @@ class AuthDriver < OpenNebulaDriver command = File.join(authN_path,ACTION[:authN].downcase) command << " '" << user.gsub("'", '\'"\'"\'') << "' '" << password.gsub("'", '\'"\'"\'') << "' " << secret - local_action(command, request_id, ACTION[:authN]) + do_action(command, request_id, nil, ACTION[:authN], + :local => true) end # Authenticate a user based in a string of the form user:secret when using the @@ -141,7 +142,8 @@ class AuthDriver < OpenNebulaDriver command = @authZ_cmd.clone command << ' ' << user_id << ' ' << requests.join(' ') - local_action(command, request_id, ACTION[:authZ]) + do_action(command, request_id, nil, ACTION[:authZ], + :local => true) end end end diff --git a/src/cli/one_helper/onehost_helper.rb b/src/cli/one_helper/onehost_helper.rb index eeaeaf613d..943e4e0010 100644 --- a/src/cli/one_helper/onehost_helper.rb +++ b/src/cli/one_helper/onehost_helper.rb @@ -59,6 +59,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper puts str % ["STATE", host.state_str] puts str % ["IM_MAD", host['IM_MAD']] puts str % ["VM_MAD", host['VM_MAD']] + puts str % ["VN_MAD", host['VN_MAD']] puts str % ["TM_MAD", host['TM_MAD']] puts str % ["LAST MONITORING TIME", host['LAST_MON_TIME']] puts diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index ffeeec15ff..1ecdd0ac87 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -99,9 +99,10 @@ class OneVMHelper < OpenNebulaHelper::OneHelper CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE TEMPLATE",false) puts vm.template_str - if vm['/VM/HISTORY_RECORDS/HISTORY'] + if vm.has_elements?("/VM/HISTORY_RECORDS/") puts - + + CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE HISTORY",false) format_history(vm) end diff --git a/src/cli/one_helper/onevnet_helper.rb b/src/cli/one_helper/onevnet_helper.rb index 5dd769841b..7216ad6abb 100644 --- a/src/cli/one_helper/onevnet_helper.rb +++ b/src/cli/one_helper/onevnet_helper.rb @@ -59,6 +59,7 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper puts str % ["PUBLIC", OpenNebulaHelper.boolean_to_str(vn['PUBLIC'])] puts str % ["TYPE", vn.type_str] puts str % ["BRIDGE", vn["BRIDGE"]] + puts str % ["VLAN", OpenNebulaHelper.boolean_to_str(vn['VLAN'])] puts str % ["PHYSICAL DEVICE", vn["PHYDEV"]] if vn["PHYDEV"] puts str % ["VLAN ID", vn["VLAN_ID"]] if vn["VLAN_ID"] puts str % ["USED LEASES", vn['TOTAL_LEASES']] @@ -128,4 +129,4 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper table end -end \ No newline at end of file +end diff --git a/src/cli/onehost b/src/cli/onehost index 6f7b5f5c81..c002900274 100755 --- a/src/cli/onehost +++ b/src/cli/onehost @@ -60,9 +60,10 @@ cmd=CommandParser::CmdParser.new(ARGV) do Creates a new Host EOT - command :create, create_desc, :hostname, :im_mad, :vmm_mad, :tm_mad do + command :create, create_desc, :hostname, :im_mad, :vmm_mad, + :tm_mad, :vnm_mad do helper.create_resource(options) do |host| - host.allocate(args[0], args[1], args[2], args[3]) + host.allocate(args[0], args[1], args[2], args[4], args[3]) end end diff --git a/src/host/Host.cc b/src/host/Host.cc index 52361a96ed..484a44953b 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -33,11 +33,13 @@ Host::Host( const string& _hostname, const string& _im_mad_name, const string& _vmm_mad_name, + const string& _vnm_mad_name, const string& _tm_mad_name): PoolObjectSQL(id,_hostname,-1,-1,"","",table), state(INIT), im_mad_name(_im_mad_name), vmm_mad_name(_vmm_mad_name), + vnm_mad_name(_vnm_mad_name), tm_mad_name(_tm_mad_name), last_monitored(0) { @@ -200,6 +202,7 @@ string& Host::to_xml(string& xml) const "" << state << "" << "" << im_mad_name << "" << "" << vmm_mad_name << "" << + "" << vnm_mad_name << "" << "" << tm_mad_name << "" << "" << last_monitored << "" << host_share.to_xml(share_xml) << @@ -231,6 +234,7 @@ int Host::from_xml(const string& xml) rc += xpath(im_mad_name, "/HOST/IM_MAD", "not_found"); rc += xpath(vmm_mad_name, "/HOST/VM_MAD", "not_found"); + rc += xpath(vnm_mad_name, "/HOST/VN_MAD", "not_found"); rc += xpath(tm_mad_name, "/HOST/TM_MAD", "not_found"); rc += xpath(last_monitored, "/HOST/LAST_MON_TIME", 0); diff --git a/src/host/HostPool.cc b/src/host/HostPool.cc index d33529cbad..b3d404a1a0 100644 --- a/src/host/HostPool.cc +++ b/src/host/HostPool.cc @@ -139,6 +139,7 @@ int HostPool::allocate ( const string& hostname, const string& im_mad_name, const string& vmm_mad_name, + const string& vnm_mad_name, const string& tm_mad_name, string& error_str) { @@ -165,6 +166,11 @@ int HostPool::allocate ( goto error_vmm; } + if ( vnm_mad_name.empty() ) + { + goto error_vnm; + } + if ( tm_mad_name.empty() ) { goto error_tm; @@ -179,7 +185,8 @@ int HostPool::allocate ( // Build a new Host object - host = new Host(-1, hostname, im_mad_name, vmm_mad_name, tm_mad_name); + host = new Host(-1, hostname, im_mad_name, vmm_mad_name, vnm_mad_name, + tm_mad_name); // Insert the Object in the pool @@ -204,6 +211,10 @@ error_vmm: oss << "VMM_MAD_NAME cannot be empty."; goto error_common; +error_vnm: + oss << "VNM_MAD_NAME cannot be empty."; + goto error_common; + error_tm: oss << "TM_MAD_NAME cannot be empty."; goto error_common; diff --git a/src/host/test/HostHookTest.cc b/src/host/test/HostHookTest.cc index 406241597e..62361519ef 100644 --- a/src/host/test/HostHookTest.cc +++ b/src/host/test/HostHookTest.cc @@ -96,7 +96,7 @@ public: { string err; - hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "tm_mad", err); + hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "vnm_mad", "tm_mad", err); CPPUNIT_ASSERT( oid >= 0 ); sleep(1); @@ -114,7 +114,7 @@ public: { string err; - hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "tm_mad", err); + hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "vnm_mad", "tm_mad", err); CPPUNIT_ASSERT( oid >= 0 ); host = hpool->get(oid, true); @@ -140,7 +140,7 @@ public: { string err; - hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "tm_mad", err); + hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "vnm_mad", "tm_mad", err); CPPUNIT_ASSERT( oid >= 0 ); host = hpool->get(oid, true); @@ -166,7 +166,7 @@ public: { string err; - hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "tm_mad", err); + hpool->allocate(&oid, "host_test", "im_mad", "vmm_mad", "vnm_mad", "tm_mad", err); CPPUNIT_ASSERT( oid >= 0 ); host = hpool->get(oid, true); diff --git a/src/host/test/HostPoolTest.cc b/src/host/test/HostPoolTest.cc index 2b63af6a50..1dab8f08d5 100644 --- a/src/host/test/HostPoolTest.cc +++ b/src/host/test/HostPoolTest.cc @@ -25,6 +25,7 @@ using namespace std; const string im_mad = "im_mad"; const string vmm_mad = "vmm_mad"; +const string vnm_mad = "vnm_mad"; const string tm_mad = "tm_mad"; const string names[] = {"Host one", "Second host"}; @@ -32,7 +33,7 @@ const string names[] = {"Host one", "Second host"}; const string xmls[] = { "0Host one0" - "im_madvmm_madtm_mad" + "im_madvmm_madvnm_madtm_mad" "0" "000" "000" @@ -41,7 +42,7 @@ const string xmls[] = "0", "1Second host0" - "im_madvmm_madtm_mad" + "im_madvmm_madvnm_madtm_mad" "0" "000" "000" @@ -53,34 +54,34 @@ const string xmls[] = // This xml dump result has the LAST_MON_TIMEs modified to 0000000000 const string xml_dump = "0a0im_madvmm_madtm_mad0" + "M_MAD>vmm_madvnm_madtm_mad0" "0000000000000" "1a name0im_madvmm_madtm_mad0vmm_madvnm_madtm_mad000000" "000000002a_name0im_madvmm_madtm_mad0vnm_madtm_mad000000000000003another " "name0im_madvmm_mad" - "tm_mad0vnm_madtm_mad000000000000004host0im_madvmm_madtm_mad" + "ATE>0im_madvmm_madvnm_madtm_mad" "0" "000" "0000" @@ -90,28 +91,28 @@ const string xml_dump = const string xml_dump_like_a = "0a0im_madvmm_madtm_mad0" + "M_MAD>vmm_madvnm_madtm_mad0" "0000000000000" "1a name0im_madvmm_madtm_mad0vmm_madvnm_madtm_mad000000" "000000002a_name0im_madvmm_madtm_mad0vnm_madtm_mad000000000000003another " "name0im_madvmm_mad" - "tm_mad0vnm_madtm_mad00000000000Host one0im_madvmm_madtm_mad00000000000000"; + "0Host one0im_madvmm_madvnm_madtm_mad00000000000000"; const string host_0_cluster = - "0Host one0im_madvmm_madtm_mad0cluster_a0000000000000"; + "0Host one0im_madvmm_madvnm_madtm_mad0cluster_a0000000000000"; /* ************************************************************************* */ /* ************************************************************************* */ @@ -162,7 +163,7 @@ protected: int oid; string err; return ((HostPool*)pool)->allocate(&oid, names[index], im_mad, - vmm_mad, tm_mad, err); + vmm_mad, vnm_mad, tm_mad, err); }; void check(int index, PoolObjectSQL* obj) @@ -184,7 +185,7 @@ protected: if( xml_str != xmls[index] ) { cout << endl << xml_str << endl << "========" - << endl << xmls[index]; + << endl << xmls[index] << endl; } //*/ CPPUNIT_ASSERT( xml_str == xmls[index]); @@ -242,16 +243,16 @@ public: // If we try to allocate two hosts with the same name and drivers, // should fail - rc = hp->allocate(&oid_0, names[0], im_mad, vmm_mad, tm_mad, err); + rc = hp->allocate(&oid_0, names[0], im_mad, vmm_mad, vnm_mad, tm_mad, err); CPPUNIT_ASSERT( oid_0 == 0 ); CPPUNIT_ASSERT( rc == oid_0 ); - rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, tm_mad, err); + rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, vnm_mad, tm_mad, err); CPPUNIT_ASSERT( oid_1 == -1 ); CPPUNIT_ASSERT( rc == oid_1 ); // the hostname can not be repeated if the drivers change - rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, tm_mad_2, err); + rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, vnm_mad, tm_mad_2, err); CPPUNIT_ASSERT( oid_1 == -1 ); CPPUNIT_ASSERT( rc == oid_1 ); @@ -272,7 +273,7 @@ public: for(int i=0; i<5; i++) { ((HostPool*)pool)->allocate(&oid, names[i], - im_mad, vmm_mad, tm_mad, err); + im_mad, vmm_mad, vnm_mad, tm_mad, err); } ostringstream oss; @@ -287,7 +288,7 @@ public: if( result != xml_dump ) { cout << endl << result << endl << "========" - << endl << xml_dump; + << endl << xml_dump << endl; } //*/ @@ -305,7 +306,7 @@ public: for(int i=0; i<5; i++) { ((HostPool*)pool)->allocate(&oid, names[i], - im_mad, vmm_mad, tm_mad, err); + im_mad, vmm_mad, vnm_mad, tm_mad, err); } @@ -321,7 +322,7 @@ public: if( result != xml_dump_like_a ) { cout << endl << result << endl << "========" - << endl << xml_dump_like_a; + << endl << xml_dump_like_a << endl; } //*/ @@ -346,7 +347,7 @@ public: { oss << "host" << i; - hp->allocate(&oid, oss.str().c_str(), im_mad, vmm_mad, tm_mad, err); + hp->allocate(&oid, oss.str().c_str(), im_mad, vmm_mad, vnm_mad, tm_mad, err); CPPUNIT_ASSERT(oid == i); if (i >=8 ) @@ -404,7 +405,7 @@ public: { oss << "host" << j; - hp->allocate(&oid, oss.str().c_str(),im_mad,vmm_mad,tm_mad,err); + hp->allocate(&oid, oss.str().c_str(),im_mad,vmm_mad,vnm_mad,tm_mad,err); } the_time2 = time(0) - the_time; @@ -433,7 +434,7 @@ public: for (i=10000,oss.str(""); i<30000 ; i++,oss.str("")) { oss << "host" << i; - hp->allocate(&oid,oss.str().c_str(),im_mad,vmm_mad,tm_mad,err); + hp->allocate(&oid,oss.str().c_str(),im_mad,vmm_mad,vnm_mad,tm_mad,err); host = hp->get(oid, false); diff --git a/src/image_mad/one_image.rb b/src/image_mad/one_image.rb index 72bb6fbbbe..2cde2db22b 100755 --- a/src/image_mad/one_image.rb +++ b/src/image_mad/one_image.rb @@ -54,12 +54,16 @@ class ImageDriver < OpenNebulaDriver @options={ :concurrency => 10, :threaded => true, - :retries => 0 + :retries => 0, + :local_actions => { + 'MV' => nil, + 'CP' => nil, + 'RM' => nil, + 'MKFS' => nil + } }.merge!(options) - super('', @options) - - @actions_path = "#{VAR_LOCATION}/remotes/image/#{fs_type}" + super("image/#{fs_type}", @options) register_action(ACTION[:mv].to_sym, method("mv")) register_action(ACTION[:cp].to_sym, method("cp")) @@ -69,19 +73,21 @@ class ImageDriver < OpenNebulaDriver # Image Manager Protocol Actions (generic implementation def mv(id, src, dst) - local_action("#{@actions_path}/mv #{src} #{dst} #{id}",id,ACTION[:mv]) + do_action("#{src} #{dst} #{id}", id, nil, + ACTION[:mv]) end def cp(id, src) - local_action("#{@actions_path}/cp #{src} #{id}",id,ACTION[:cp]) + do_action("#{src} #{id}", id, nil, ACTION[:cp]) end def rm(id, dst) - local_action("#{@actions_path}/rm #{dst} #{id}",id,ACTION[:rm]) + do_action("#{dst} #{id}", id, nil, ACTION[:rm]) end def mkfs(id, fs, size) - local_action("#{@actions_path}/mkfs #{fs} #{size} #{id}",id,ACTION[:mkfs]) + do_action("#{fs} #{size} #{id}", id, nil, + ACTION[:mkfs]) end end diff --git a/src/lcm/test/LifeCycleManagerTest.cc b/src/lcm/test/LifeCycleManagerTest.cc index c2d4386d2e..2f333133d5 100644 --- a/src/lcm/test/LifeCycleManagerTest.cc +++ b/src/lcm/test/LifeCycleManagerTest.cc @@ -47,6 +47,7 @@ const string templates[] = static int hid = 123; static string hostname = "test_hostname"; static string vmm_mad = "vmm_mad"; +static string vnm_mad = "vnm_mad"; static string tm_mad = "tm_mad"; static string vmdir = "vmdir"; @@ -225,7 +226,7 @@ private: vm->lock(); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -489,7 +490,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -573,7 +574,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -594,7 +595,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -615,7 +616,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -637,7 +638,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -661,7 +662,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -685,7 +686,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -749,7 +750,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -772,7 +773,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -795,7 +796,7 @@ public: { vm = allocate_running(0); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); diff --git a/src/mad/ruby/ActionManager.rb b/src/mad/ruby/ActionManager.rb index fe0eb02f55..dfdea8aa8c 100644 --- a/src/mad/ruby/ActionManager.rb +++ b/src/mad/ruby/ActionManager.rb @@ -16,6 +16,7 @@ require 'thread' =begin rdoc + This class provides support to handle actions. Class methods, or actions, can be registered in the action manager. The manager will wait for actions to be triggered (thread-safe), and will execute them concurrently. The action manager diff --git a/src/mad/ruby/DriverExecHelper.rb b/src/mad/ruby/DriverExecHelper.rb new file mode 100644 index 0000000000..d6b632b7e0 --- /dev/null +++ b/src/mad/ruby/DriverExecHelper.rb @@ -0,0 +1,194 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +# This module provides an abstraction to generate an execution context for +# OpenNebula Drivers. The module has been designed to be included as part +# of a driver and not to be used standalone. +module DriverExecHelper + # Action result strings for messages + RESULT = { + :success => "SUCCESS", + :failure => "FAILURE" + } + + def self.failed?(rc_str) + return rc_str == RESULT[:failure] + end + + #Initialize module variables + def initialize_helper(directory, options) + @config = read_configuration + @remote_scripts_base_path = @config['SCRIPTS_REMOTE_DIR'] + + @local_actions = options[:local_actions] + + if ENV['ONE_LOCATION'] == nil + @local_scripts_base_path = "/var/lib/one/remotes" + else + @local_scripts_base_path = "#{ENV['ONE_LOCATION']}/var/remotes" + end + + # dummy paths + @remote_scripts_path = File.join(@remote_scripts_base_path, directory) + @local_scripts_path = File.join(@local_scripts_base_path, directory) + end + + # + # METHODS FOR COMMAND LINE & ACTION PATHS + # + # Given the action name and the parameter returns full path of the script + # and appends its parameters. It uses @local_actions hash to know if the + # actions is remote or local. If the local actions has defined an special + # script name this is used, otherwise the action name in downcase is + # used as the script name. + # + # @param [String, Symbol] action name of the action + # @param [String] parameters arguments for the script + # @param [String, nil] default_name alternative name for the script + # @return [String] command line needed to execute the action + def action_command_line(action, parameters, default_name=nil) + if action_is_local? action + script_path=@local_scripts_path + else + script_path=@remote_scripts_path + end + + File.join(script_path, action_script_name(action, default_name))+ + " "+parameters + end + + # True if the action is meant to be executed locally + # + # @param [String, Symbol] action name of the action + def action_is_local?(action) + @local_actions.include? action.to_s.upcase + end + + # Name of the script file for the given action + # + # @param [String, Symbol] action name of the action + # @param [String, nil] default_name alternative name for the script + def action_script_name(action, default_name=nil) + name=@local_actions[action.to_s.upcase] + + if name + name + else + default_name || action.to_s.downcase + end + end + + # + # METHODS FOR LOGS & COMMAND OUTPUT + # + # Sends a log message to ONE. The +message+ can be multiline, it will + # be automatically splitted by lines. + def log(number, message) + in_error_message=false + msg=message.strip + msg.each_line {|line| + severity='I' + + l=line.strip + + if l=='ERROR MESSAGE --8<------' + in_error_message=true + next + elsif l=='ERROR MESSAGE ------>8--' + in_error_message=false + next + else + if in_error_message + severity='E' + elsif line.match(/^(ERROR|DEBUG|INFO):(.*)$/) + line=$2 + case $1 + when 'ERROR' + severity='E' + when 'DEBUG' + severity='D' + when 'INFO' + severity='I' + else + severity='I' + end + end + end + + send_message("LOG", severity, number, line.strip) + } + end + + # Generates a proc with that calls log with a hardcoded number. It will + # be used to add loging to command actions + def log_method(num) + lambda {|message| + log(num, message) + } + end + + #This method returns the result in terms + def get_info_from_execution(command_exe) + if command_exe.code == 0 + result = RESULT[:success] + info = command_exe.stdout + else + result = RESULT[:failure] + info = command_exe.get_error_message + end + + info = "-" if info == nil || info.empty? + + [result, info] + end + + # + # + # Simple parser for the config file generated by OpenNebula + def read_configuration + one_config=nil + + if ENV['ONE_LOCATION'] + one_config = ENV['ONE_LOCATION']+'/var/config' + else + one_config = '/var/lib/one/config' + end + + config=Hash.new + cfg='' + + begin + open(one_config) do |file| + cfg=file.read + end + + cfg.split(/\n/).each do |line| + m=line.match(/^([^=]+)=(.*)$/) + + if m + name=m[1].strip.upcase + value=m[2].strip + config[name]=value + end + end + rescue Exception => e + STDERR.puts "Error reading config: #{e.inspect}" + STDERR.flush + end + + config + end +end diff --git a/src/mad/ruby/OpenNebulaDriver.rb b/src/mad/ruby/OpenNebulaDriver.rb index 6129795d3a..316ca92af2 100644 --- a/src/mad/ruby/OpenNebulaDriver.rb +++ b/src/mad/ruby/OpenNebulaDriver.rb @@ -17,9 +17,7 @@ require "ActionManager" require "CommandManager" -# Author:: dsa-research.org -# Copyright:: (c) OpenNebula Project Leads (OpenNebula.org) -# License:: Apache License +require "DriverExecHelper" # This class provides basic messaging and logging functionality # to implement OpenNebula Drivers. A driver is a program that @@ -30,11 +28,117 @@ require "CommandManager" # for each action it wants to receive. The method must be associated # with the action name through the register_action function class OpenNebulaDriver < ActionManager + include DriverExecHelper + # @return [String] Base path for scripts attr_reader :local_scripts_base_path, :remote_scripts_base_path # @return [String] Path for scripts attr_reader :local_scripts_path, :remote_scripts_path + # Initialize OpenNebulaDriver object + # + # @param [String] directory path inside the remotes directory where the + # scripts are located + # @param [Hash] options named options to change the object's behaviour + # @option options [Number] :concurrency (10) max number of threads + # @option options [Boolean] :threaded (true) enables or disables threads + # @option options [Number] :retries (0) number of retries to copy scripts + # to the remote host + # @option options [Hash] :local_actions ({}) hash with the actions + # executed locally and the name of the script if it differs from the + # default one. This hash can be constructed using {parse_actions_list} + def initialize(directory, options={}) + @options={ + :concurrency => 10, + :threaded => true, + :retries => 0, + :local_actions => {} + }.merge!(options) + + super(@options[:concurrency], @options[:threaded]) + + @retries = @options[:retries] + + @send_mutex = Mutex.new + + #Set default values + initialize_helper(directory, @options) + + register_action(:INIT, method("init")) + end + + # Sends a message to the OpenNebula core through stdout + def send_message(action="-", result=RESULT[:failure], id="-", info="-") + @send_mutex.synchronize { + STDOUT.puts "#{action} #{result} #{id} #{info}" + STDOUT.flush + } + end + + # Calls remotes or local action checking the action name and + # @local_actions. Optional arguments can be specified as a hash + # + # @param [String] parameters arguments passed to the script + # @param [Number, String] id action identifier + # @param [String] host hostname where the action is going to be executed + # @param [String, Symbol] aname name of the action + # @param [Hash] ops extra options for the command + # @option ops [String] :stdin text to be writen to stdin + # @option ops [String] :script_name default script name for the action, + # action name is used by defaults + # @option ops [String] :respond if defined will send result to ONE core + # @option ops [String] :local if defined will execute the action locally + def do_action(parameters, id, host, aname, ops={}) + options={ + :stdin => nil, + :script_name => nil, + :respond => true, + :ssh_stream => nil + }.merge(ops) + + params = parameters+" #{id} #{host}" + command = action_command_line(aname, params, options[:script_name]) + + if options[:local] || action_is_local?(aname) + execution = LocalCommand.run(command, log_method(id)) + elsif options[:ssh_stream] + if options[:stdin] + cmdin = "cat << EOT | #{command}" + stdin = "#{options[:stdin]}\nEOT\n" + else + cmdin = command + stdin = nil + end + + execution = options[:ssh_stream].run(cmdin, stdin, command) + + else + execution = RemotesCommand.run(command, + host, + @remote_scripts_base_path, + log_method(id), + options[:stdin], + @retries) + end + + result, info = get_info_from_execution(execution) + + if options[:respond] + send_message(aname,result,id,info) + end + + [result, info] + end + + + # Start the driver. Reads from STDIN and executes methods associated with + # the messages + def start_driver + loop_thread = Thread.new { loop } + start_listener + loop_thread.kill + end + # This function parses a string with this form: # # 'deploy,shutdown,poll=poll_ganglia, cancel ' @@ -69,238 +173,6 @@ class OpenNebulaDriver < ActionManager actions end - # Action result strings for messages - RESULT = { - :success => "SUCCESS", - :failure => "FAILURE" - } - - # Initialize OpenNebulaDriver object - # - # @param [String] directory path inside the remotes directory where the - # scripts are located - # @param [Hash] options named options to change the object's behaviour - # @option options [Number] :concurrency (10) max number of threads - # @option options [Boolean] :threaded (true) enables or disables threads - # @option options [Number] :retries (0) number of retries to copy scripts - # to the remote host - # @option options [Hash] :local_actions ({}) hash with the actions - # executed locally and the name of the script if it differs from the - # default one. This hash can be constructed using {parse_actions_list} - def initialize(directory, options={}) - @options={ - :concurrency => 10, - :threaded => true, - :retries => 0, - :local_actions => {} - }.merge!(options) - - super(@options[:concurrency], @options[:threaded]) - - @retries = @options[:retries] - @local_actions = @options[:local_actions] - - @send_mutex = Mutex.new - - # set default values - @config = read_configuration - @remote_scripts_base_path = @config['SCRIPTS_REMOTE_DIR'] - - if ENV['ONE_LOCATION'] == nil - @local_scripts_base_path = "/var/lib/one/remotes" - else - @local_scripts_base_path = "#{ENV['ONE_LOCATION']}/var/remotes" - end - - # dummy paths - @remote_scripts_path = File.join(@remote_scripts_base_path, directory) - @local_scripts_path = File.join(@local_scripts_base_path, directory) - - register_action(:INIT, method("init")) - end - - # Sends a message to the OpenNebula core through stdout - def send_message(action="-", result=RESULT[:failure], id="-", info="-") - @send_mutex.synchronize { - STDOUT.puts "#{action} #{result} #{id} #{info}" - STDOUT.flush - } - end - - # Calls remotes or local action checking the action name and - # @local_actions. Optional arguments can be specified as a hash - # - # @param [String] parameters arguments passed to the script - # @param [Number, String] id action identifier - # @param [String] host hostname where the action is going to be executed - # @param [String, Symbol] aname name of the action - # @param [Hash] ops extra options for the command - # @option ops [String] :stdin text to be writen to stdin - # @option ops [String] :script_name default script name for the action, - # action name is used by defaults - def do_action(parameters, id, host, aname, ops={}) - options={ - :stdin => nil, - :script_name => nil - }.merge(ops) - - params=parameters+" #{id} #{host}" - - command=action_command_line(aname, params, options[:script_name]) - - if action_is_local? aname - local_action(command, id, aname) - else - remotes_action(command, id, host, aname, @remote_scripts_base_path, - options[:stdin]) - end - end - - # Given the action name and the parameter returns full path of the script - # and appends its parameters. It uses @local_actions hash to know if the - # actions is remote or local. If the local actions has defined an special - # script name this is used, otherwise the action name in downcase is - # used as the script name. - # - # @param [String, Symbol] action name of the action - # @param [String] parameters arguments for the script - # @param [String, nil] default_name alternative name for the script - # @return [String] command line needed to execute the action - def action_command_line(action, parameters, default_name=nil) - if action_is_local? action - script_path=@local_scripts_path - else - script_path=@remote_scripts_path - end - - File.join(script_path, action_script_name(action, default_name))+ - " "+parameters - end - - # True if the action is meant to be executed locally - # - # @param [String, Symbol] action name of the action - def action_is_local?(action) - @local_actions.include? action.to_s.upcase - end - - # Name of the script file for the given action - # - # @param [String, Symbol] action name of the action - # @param [String, nil] default_name alternative name for the script - def action_script_name(action, default_name=nil) - name=@local_actions[action.to_s.upcase] - - if name - name - else - default_name || action.to_s.downcase - end - end - - # Execute a command associated to an action and id in a remote host. - # - # @param [String] command command line to execute the script - # @param [Number, String] id action identifier - # @param [String] host hostname where the action is going to be executed - # @param [String, Symbol] aname name of the action - # @param [String] remote_dir path where the remotes reside - # @param [String, nil] std_in input of the string from the STDIN - def remotes_action(command, id, host, aname, remote_dir, std_in=nil) - command_exe = RemotesCommand.run(command, - host, - remote_dir, - log_method(id), - std_in, - @retries) - if command_exe.code == 0 - result = RESULT[:success] - info = command_exe.stdout - else - result = RESULT[:failure] - info = command_exe.get_error_message - end - - info = "-" if info == nil || info.empty? - - send_message(aname,result,id,info) - end - - # Execute a command associated to an action and id on localhost - # - # @param [String] command command line to execute the script - # @param [Number, String] id action identifier - # @param [String, Symbol] aname name of the action - def local_action(command, id, aname) - command_exe = LocalCommand.run(command, log_method(id)) - - if command_exe.code == 0 - result = RESULT[:success] - info = command_exe.stdout - else - result = RESULT[:failure] - info = command_exe.get_error_message - end - - info = "-" if info == nil || info.empty? - - send_message(aname,result,id,info) - end - - # Sends a log message to ONE. The +message+ can be multiline, it will - # be automatically splitted by lines. - def log(number, message) - in_error_message=false - msg=message.strip - msg.each_line {|line| - severity='I' - - l=line.strip - - if l=='ERROR MESSAGE --8<------' - in_error_message=true - next - elsif l=='ERROR MESSAGE ------>8--' - in_error_message=false - next - else - if in_error_message - severity='E' - elsif line.match(/^(ERROR|DEBUG|INFO):(.*)$/) - line=$2 - case $1 - when 'ERROR' - severity='E' - when 'DEBUG' - severity='D' - when 'INFO' - severity='I' - else - severity='I' - end - end - end - - send_message("LOG", severity, number, line.strip) - } - end - - # Generates a proc with that calls log with a hardcoded number. It will - # be used to add loging to command actions - def log_method(num) - lambda {|message| - log(num, message) - } - end - - # Start the driver. Reads from STDIN and executes methods associated with - # the messages - def start_driver - loop_thread = Thread.new { loop } - start_listener - loop_thread.kill - end - private def init @@ -333,40 +205,6 @@ private end end end - - def read_configuration - one_config=nil - - if ENV['ONE_LOCATION'] - one_config=ENV['ONE_LOCATION']+'/var/config' - else - one_config='/var/lib/one/config' - end - - config=Hash.new - cfg='' - - begin - open(one_config) do |file| - cfg=file.read - end - - cfg.split(/\n/).each do |line| - m=line.match(/^([^=]+)=(.*)$/) - - if m - name=m[1].strip.upcase - value=m[2].strip - config[name]=value - end - end - rescue Exception => e - STDERR.puts "Error reading config: #{e.inspect}" - STDERR.flush - end - - config - end end ################################################################ diff --git a/src/mad/ruby/VirtualMachineDriver.rb b/src/mad/ruby/VirtualMachineDriver.rb index 06240a8ac1..f9f5fc1c21 100644 --- a/src/mad/ruby/VirtualMachineDriver.rb +++ b/src/mad/ruby/VirtualMachineDriver.rb @@ -15,6 +15,8 @@ #--------------------------------------------------------------------------- # require "OpenNebulaDriver" require "CommandManager" +require 'base64' +require 'rexml/document' # Author:: dsa-research.org # Copyright:: (c) 2011 Universidad Computense de Madrid @@ -85,26 +87,15 @@ class VirtualMachineDriver < OpenNebulaDriver register_action(ACTION[:poll].to_sym, method("poll")) end - # Converts a deployment file from its remote path to the local (front-end) - # path - def get_local_deployment_file(rfile) - lfile = nil + # Decodes the encoded XML driver message received from the core + # + # @param [String] drv_message the driver message + # @return [REXML::Element] the root element of the decoded XML message + def decode(drv_message) + message = Base64.decode64(drv_message) + xml_doc = REXML::Document.new(message) - one_location = ENV["ONE_LOCATION"] - - if one_location == nil - var_location = "/var/lib/one/" - else - var_location = one_location + "/var/" - end - - m = rfile.match(/.*?\/(\d+)\/images\/(deployment.\d+)$/) - - lfile = "#{var_location}#{m[1]}/#{m[2]}" if m - - lfile = nil if lfile and !File.exists?(lfile) - - return lfile + xml_doc.root end # Execute a command associated to an action and id in a remote host. @@ -118,37 +109,37 @@ class VirtualMachineDriver < OpenNebulaDriver end # Virtual Machine Manager Protocol Actions (generic implementation) - def deploy(id, host, remote_dfile, not_used) + def deploy(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:deploy],RESULT[:failure],id,error) end - def shutdown(id, host, deploy_id, not_used) + def shutdown(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:shutdown],RESULT[:failure],id,error) end - def cancel(id, host, deploy_id, not_used) + def cancel(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:cancel],RESULT[:failure],id,error) end - def save(id, host, deploy_id, file) + def save(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:save],RESULT[:failure],id,error) end - def restore(id, host, deploy_id, file) + def restore(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:restore],RESULT[:failure],id,error) end - def migrate(id, host, deploy_id, dest_host) + def migrate(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:migrate],RESULT[:failure],id,error) end - def poll(id, host, deploy_id, not_used) + def poll(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:poll],RESULT[:failure],id,error) end diff --git a/src/mad/ruby/scripts_common.rb b/src/mad/ruby/scripts_common.rb index ba24205e20..8251ae48ff 100644 --- a/src/mad/ruby/scripts_common.rb +++ b/src/mad/ruby/scripts_common.rb @@ -43,11 +43,18 @@ module OpenNebula # This function is used to pass error message to the mad def self.error_message(message) - STDERR.puts "ERROR MESSAGE --8<------" - STDERR.puts message - STDERR.puts "ERROR MESSAGE ------>8--" + STDERR.puts format_error_message(message) end + #This function formats an error message for OpenNebula Copyright e + def self.format_error_message(message) + error_str = "ERROR MESSAGE --8<------\n" + error_str << message + error_str << "\nERROR MESSAGE ------>8--" + + return error_str + end + # Executes a command, if it fails returns error message and exits # If a second parameter is present it is used as the error message when # the command fails diff --git a/src/mad/ruby/ssh_stream.rb b/src/mad/ruby/ssh_stream.rb new file mode 100644 index 0000000000..067227beeb --- /dev/null +++ b/src/mad/ruby/ssh_stream.rb @@ -0,0 +1,238 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +require 'CommandManager' +require 'open3' +require 'scripts_common' + +class SshStream + attr_reader :stream_out, :stream_err, :stdin + attr_reader :out, :err + + # + # + EOF_ERR = "EOF_ERR" + EOF_OUT = "EOF_OUT" + RC_STR = "ExitCode: " + SSH_RC_STR = "ExitSSHCode: " + + EOF_CMD = "echo \"#{RC_STR}$? #{EOF_ERR}\" 1>&2; echo \"#{EOF_OUT}\"" + SSH_CMD = "ssh" + # + # + # + def initialize(host) + @host = host + end + + def opened? + defined?(@stdin) + end + + def alive? + @alive == true + end + + def open + @stdin, @stdout, @stderr=Open3::popen3("#{SSH_CMD} #{@host} bash -s ; echo #{SSH_RC_STR} $? 1>&2") + + @stream_out = "" + @stream_err = "" + + @out = "" + @err = "" + + @alive = true + end + + def close + begin + @stdin.puts "\nexit" + rescue #rescue from EPIPE if ssh command exited already + end + + @stdin.close if not @stdin.closed? + @stdout.close if not @stdout.closed? + @stderr.close if not @stderr.closed? + + @alive = false + end + + def exec(command) + return if ! @alive + + @out = "" + @err = "" + + begin + cmd="(#{command}); #{EOF_CMD}" + + sliced=cmd.scan(/.{1,100}/) + + sliced.each do |slice| + @stdin.write slice + @stdin.flush + end + + @stdin.write "\n" + @stdin.flush + rescue + + end + end + + def wait_for_command + done_out = false + done_err = false + + code = -1 + + while not (done_out and done_err ) and @alive + rc, rw, re= IO.select([@stdout, @stderr],[],[]) + + rc.each { |fd| + begin + c = fd.read_nonblock(100) + next if !c + rescue #rescue from EOF if ssh command finishes and closes fds + next + end + + if fd == @stdout + @out << c + done_out = true if @out.slice!("#{EOF_OUT}\n") + else + @err << c + + tmp = @err.scan(/^#{SSH_RC_STR}(\d+)$/) + + if tmp[0] + message = "Error connecting to #{@host}" + code = tmp[0][0].to_i + + @err << OpenNebula.format_error_message(message) + + @alive = false + break + end + + tmp = @err.scan(/^#{RC_STR}(\d*) #{EOF_ERR}\n/) + + if tmp[0] + code = tmp[0][0].to_i + done_err = true + + @err.slice!(" #{EOF_ERR}\n") + end + end + } + end + + @stream_out << @out + @stream_err << @err + + return code + end + + def exec_and_wait(command) + exec(command) + wait_for_command + end +end + + +class SshStreamCommand < RemotesCommand + def initialize(host, remote_dir, logger=nil, stdin=nil) + super('true', host, logger, stdin) + + @remote_dir = remote_dir + @stream = SshStream.new(host) + + @stream.open + end + + def run(command, stdin=nil, base_cmd = nil) + @stream.open unless @stream.opened? + + if base_cmd #Check if base command is on remote host + chk_cmd = "if [ ! -x \"#{base_cmd.match(/\S*/)[0]}\" ]; \ + then exit #{MAGIC_RC} 1>&2; \ + fi" + + if @stream.exec_and_wait(chk_cmd) == MAGIC_RC + RemotesCommand.update_remotes(@host, @remote_dir, @logger) + end + end + + @stream.exec(command) + @stream.stdin.write(stdin) if stdin + + @code = @stream.wait_for_command + + @stdout = @stream.out + @stderr = @stream.err + + if @code != 0 + log("Command execution fail: #{command}") + end + + log(@stderr) + + return self + end +end + + +if $0 == __FILE__ + + ssh=SshStream.new('localhost') + + ssh.open + + ssh.exec("date | tee /tmp/test.javi") + code=ssh.wait_for_command + + puts "Code: #{code}" + puts "output: #{ssh.out}" + + ssh.exec "cat << EOT | cat" + ssh.stdin.puts "blah blah\nmas blah\nrequeteblah" + ssh.stdin.puts "EOT" + + code=ssh.wait_for_command + + puts "Code: #{code}" + puts "output: #{ssh.out}" + + code=ssh.exec_and_wait("whoami") + + puts "Code: #{code}" + puts "output: #{ssh.out}" + + code=ssh.exec_and_wait("touch /etc/pepe.txt") + + puts "Code: #{code}" + puts "output: #{ssh.out}" + puts "output err: #{ssh.err}" + + ssh.close + + cssh = SshStreamCommand.new('no_host', + '/tmp', + lambda { |e| STDOUT.puts "error: #{e}" }, + nil) + cssh.run('whoami') +end \ No newline at end of file diff --git a/src/oca/java/src/org/opennebula/client/host/Host.java b/src/oca/java/src/org/opennebula/client/host/Host.java index 20a82df64b..0cc9d646d7 100644 --- a/src/oca/java/src/org/opennebula/client/host/Host.java +++ b/src/oca/java/src/org/opennebula/client/host/Host.java @@ -72,6 +72,9 @@ public class Host extends PoolElement{ * @param vmm The name of the virtual machine manager mad name * (vmm_mad_name), this values are taken from the oned.conf with the * tag name VM_MAD (name) + * @param vnm The name of the virtual network manager mad name + * (vnm_mad_name), this values are taken from the oned.conf with the + * tag name VN_MAD (name) * @param tm The transfer manager mad name to be used with this host * @return If successful the message contains the associated * id generated for this host @@ -80,9 +83,10 @@ public class Host extends PoolElement{ String hostname, String im, String vmm, + String vnm, String tm) { - return client.call(ALLOCATE, hostname, im, vmm, tm); + return client.call(ALLOCATE, hostname, im, vmm, vnm, tm); } /** diff --git a/src/oca/java/test/HostTest.java b/src/oca/java/test/HostTest.java index 81f1878b6a..dfb58022fc 100644 --- a/src/oca/java/test/HostTest.java +++ b/src/oca/java/test/HostTest.java @@ -63,7 +63,8 @@ public class HostTest @Before public void setUp() throws Exception { - res = Host.allocate(client, name, "im_dummy", "vmm_dummy", "tm_dummy"); + res = Host.allocate(client, name, "im_dummy", "vmm_dummy", "vnm_dummy", + "tm_dummy"); int hid = !res.isError() ? Integer.parseInt(res.getMessage()) : -1; host = new Host(hid, client); @@ -83,7 +84,8 @@ public class HostTest { String name = "allocate_test"; - res = Host.allocate(client, name, "im_dummy", "vmm_dummy", "tm_dummy"); + res = Host.allocate(client, name, "im_dummy", "vmm_dummy", "vmm_dummy", + "tm_dummy"); assertTrue( !res.isError() ); // assertTrue( res.getMessage().equals("0") ); diff --git a/src/oca/java/test/VirtualMachineTest.java b/src/oca/java/test/VirtualMachineTest.java index 115042df16..1f2bacd492 100644 --- a/src/oca/java/test/VirtualMachineTest.java +++ b/src/oca/java/test/VirtualMachineTest.java @@ -80,11 +80,11 @@ public class VirtualMachineTest res = Host.allocate(client, "host_A", - "im_dummy", "vmm_dummy", "tm_dummy"); + "im_dummy", "vmm_dummy", "vmm_dummy", "tm_dummy"); hid_A = Integer.parseInt( res.getMessage() ); res = Host.allocate(client, "host_B", - "im_dummy", "vmm_dummy", "tm_dummy"); + "im_dummy", "vmm_dummy", "vmm_dummy", "tm_dummy"); hid_B = Integer.parseInt( res.getMessage() ); } diff --git a/src/oca/ruby/OpenNebula/Host.rb b/src/oca/ruby/OpenNebula/Host.rb index 24f205663c..7a66b9ee86 100644 --- a/src/oca/ruby/OpenNebula/Host.rb +++ b/src/oca/ruby/OpenNebula/Host.rb @@ -78,15 +78,15 @@ module OpenNebula # Allocates a new Host in OpenNebula # - # +hostname+ A string containing the name of the new Host. + # @param hostname [String] Name of the new Host. + # @param im [String] Name of the im_driver + # @param vmm [String] Name of the vmm_driver + # @param tm [String] Name of the tm_driver # - # +im+ A string containing the name of the im_driver - # - # +vmm+ A string containing the name of the vmm_driver - # - # +tm+ A string containing the name of the tm_driver - def allocate(hostname,im,vmm,tm) - super(HOST_METHODS[:allocate],hostname,im,vmm,tm) + # @return [Integer, OpenNebula::Error] the new VM ID in case of + # success, error otherwise + def allocate(hostname,im,vmm,vnm,tm) + super(HOST_METHODS[:allocate],hostname,im,vmm,vnm,tm) end # Deletes the Host diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index eb60f27e08..6d0eded4cc 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -212,11 +212,13 @@ int HostAllocate::pool_allocate(xmlrpc_c::paramList const& paramList, string host = xmlrpc_c::value_string(paramList.getString(1)); string im_mad = xmlrpc_c::value_string(paramList.getString(2)); string vmm_mad = xmlrpc_c::value_string(paramList.getString(3)); - string tm_mad = xmlrpc_c::value_string(paramList.getString(4)); + string vnm_mad = xmlrpc_c::value_string(paramList.getString(4)); + string tm_mad = xmlrpc_c::value_string(paramList.getString(5)); HostPool * hpool = static_cast(pool); - return hpool->allocate(&id, host, im_mad, vmm_mad, tm_mad, error_str); + return hpool->allocate(&id, host, im_mad, vmm_mad, vnm_mad, tm_mad, + error_str); } /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 02d2755661..9d4aacd84b 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -86,9 +86,10 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int RequestManagerVirtualMachine::get_host_information(int hid, - string& name, +int RequestManagerVirtualMachine::get_host_information(int hid, + string& name, string& vmm, + string& vnm, string& tm, RequestAttributes& att) { @@ -110,6 +111,7 @@ int RequestManagerVirtualMachine::get_host_information(int hid, name = host->get_name(); vmm = host->get_vmm_mad(); + vnm = host->get_vnm_mad(); tm = host->get_tm_mad(); host->unlock(); @@ -142,6 +144,7 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm, int hid, const string& hostname, const string& vmm_mad, + const string& vnm_mad, const string& tm_mad, RequestAttributes& att) { @@ -154,7 +157,7 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm, nd.get_configuration_attribute("VM_DIR",vmdir); - vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad); + vm->add_history(hid,hostname,vmdir,vmm_mad,vnm_mad,tm_mad); rc = vmpool->update_history(vm); @@ -273,6 +276,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, string hostname; string vmm_mad; + string vnm_mad; string tm_mad; int id = xmlrpc_c::value_int(paramList.getInt(1)); @@ -283,7 +287,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, return; } - if (get_host_information(hid,hostname,vmm_mad,tm_mad, att) != 0) + if (get_host_information(hid,hostname,vmm_mad,vnm_mad,tm_mad, att) != 0) { return; } @@ -303,7 +307,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, return; } - if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0) + if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,tm_mad,att) != 0) { vm->unlock(); return; @@ -329,6 +333,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList string hostname; string vmm_mad; + string vnm_mad; string tm_mad; int id = xmlrpc_c::value_int(paramList.getInt(1)); @@ -340,7 +345,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList return; } - if (get_host_information(hid,hostname,vmm_mad,tm_mad,att) != 0) + if (get_host_information(hid,hostname,vmm_mad,vnm_mad,tm_mad,att) != 0) { return; } @@ -362,7 +367,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList return; } - if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0) + if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,tm_mad,att) != 0) { vm->unlock(); return; diff --git a/src/sunstone/models/OpenNebulaJSON/HostJSON.rb b/src/sunstone/models/OpenNebulaJSON/HostJSON.rb index d4395231bb..cf24bb1ee9 100644 --- a/src/sunstone/models/OpenNebulaJSON/HostJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/HostJSON.rb @@ -27,9 +27,10 @@ module OpenNebulaJSON end self.allocate(host_hash['name'], - host_hash['im_mad'], - host_hash['vm_mad'], - host_hash['tm_mad']) + host_hash['im_mad'], + host_hash['vm_mad'], + host_hash['vnm_mad'], + host_hash['tm_mad']) end def delete diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js index c54d9a78d9..cfbf85d2f7 100644 --- a/src/sunstone/public/js/plugins/hosts-tab.js +++ b/src/sunstone/public/js/plugins/hosts-tab.js @@ -80,10 +80,19 @@ var create_host_tmpl = \ \ \ +
\ + \ + \ +
\
\ \ \ @@ -443,6 +452,10 @@ function updateHostInfo(request,host){ VM MAD\ '+host_info.VM_MAD+'\ \ + \ + VN MAD\ + '+host_info.VN_MAD+'\ + \ \ TM MAD\ '+host_info.TM_MAD+'\ @@ -537,6 +550,7 @@ function setupCreateHostDialog(){ "name": $('#name',this).val(), "tm_mad": $('#tm_mad :selected',this).val(), "vm_mad": $('#vmm_mad :selected',this).val(), + "vnm_mad": $('#vnm_mad :selected',this).val(), "im_mad": $('#im_mad :selected',this).val() } } diff --git a/src/template/template_syntax.cc b/src/template/template_syntax.cc index 3aadc30534..3b547760de 100644 --- a/src/template/template_syntax.cc +++ b/src/template/template_syntax.cc @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.2" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -74,7 +73,7 @@ /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 17 "template_syntax.y" #include @@ -127,8 +126,8 @@ extern "C" -/* Line 189 of yacc.c */ -#line 132 "template_syntax.cc" +/* Line 268 of yacc.c */ +#line 131 "template_syntax.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -171,7 +170,7 @@ extern "C" typedef union YYSTYPE { -/* Line 214 of yacc.c */ +/* Line 293 of yacc.c */ #line 74 "template_syntax.y" char * val_str; @@ -179,8 +178,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 184 "template_syntax.cc" +/* Line 293 of yacc.c */ +#line 183 "template_syntax.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -204,8 +203,8 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 209 "template_syntax.cc" +/* Line 343 of yacc.c */ +#line 208 "template_syntax.cc" #ifdef short # undef short @@ -308,11 +307,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -335,24 +334,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -383,23 +382,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -419,6 +402,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 6 /* YYLAST -- Last index in YYTABLE. */ @@ -528,8 +531,8 @@ static const yytype_uint8 yyr2[] = 0, 2, 1, 2, 3, 5, 2, 3, 5 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -560,8 +563,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -569,6 +571,12 @@ static const yytype_uint8 yytable[] = 12, 15, 17, 16, 18, 7 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-8)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_uint8 yycheck[] = { 0, 3, 9, 9, 5, 7, 4, 8, 6, 9, @@ -616,7 +624,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -880,7 +887,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -983,115 +989,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1132,6 +1165,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, mc, tmpl, error_msg) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1148,12 +1182,9 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1219,7 +1250,7 @@ YYLTYPE yylloc; YYLTYPE *yylsp; /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[2]; + YYLTYPE yyerror_range[3]; YYSIZE_T yystacksize; @@ -1368,7 +1399,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1399,8 +1430,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1456,7 +1487,7 @@ yyreduce: { case 4: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 99 "template_syntax.y" { Attribute * pattr; @@ -1466,12 +1497,12 @@ yyreduce: pattr = new SingleAttribute(name,unescape(value)); tmpl->set(pattr); - ;} + } break; case 5: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 109 "template_syntax.y" { Attribute * pattr; @@ -1484,12 +1515,12 @@ yyreduce: tmpl->set(pattr); delete amap; - ;} + } break; case 6: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 122 "template_syntax.y" { Attribute * pattr; @@ -1499,12 +1530,12 @@ yyreduce: pattr = new SingleAttribute(name,value); tmpl->set(pattr); - ;} + } break; case 7: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 134 "template_syntax.y" { map* vattr; @@ -1517,12 +1548,12 @@ yyreduce: vattr->insert(make_pair(name,unescape(value))); (yyval.val_attr) = static_cast(vattr); - ;} + } break; case 8: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 147 "template_syntax.y" { string name((yyvsp[(3) - (5)].val_str)); @@ -1535,15 +1566,26 @@ yyreduce: attrmap->insert(make_pair(name,unescape(value))); (yyval.val_attr) = (yyvsp[(1) - (5)].val_attr); - ;} + } break; -/* Line 1464 of yacc.c */ -#line 1545 "template_syntax.cc" +/* Line 1806 of yacc.c */ +#line 1576 "template_syntax.cc" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1572,6 +1614,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1579,41 +1625,40 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (&yylloc, mc, tmpl, error_msg, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, mc, tmpl, error_msg, yymsg); - } - else - { - yyerror (&yylloc, mc, tmpl, error_msg, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, mc, tmpl, error_msg, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } - yyerror_range[0] = yylloc; + yyerror_range[1] = yylloc; if (yyerrstatus == 3) { @@ -1650,7 +1695,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - yyerror_range[0] = yylsp[1-yylen]; + yyerror_range[1] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); @@ -1669,7 +1714,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1684,7 +1729,7 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - yyerror_range[0] = *yylsp; + yyerror_range[1] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, mc, tmpl, error_msg); YYPOPSTACK (1); @@ -1694,10 +1739,10 @@ yyerrlab1: *++yyvsp = yylval; - yyerror_range[1] = yylloc; + yyerror_range[2] = yylloc; /* Using YYLLOC is tempting, but would change the location of the lookahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); *++yylsp = yyloc; /* Shift the error token. */ @@ -1733,8 +1778,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, mc, tmpl, error_msg); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, mc, tmpl, error_msg); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1759,7 +1809,7 @@ yyreturn: -/* Line 1684 of yacc.c */ +/* Line 2067 of yacc.c */ #line 160 "template_syntax.y" diff --git a/src/template/template_syntax.h b/src/template/template_syntax.h index dcef6a9d96..aa9ae6b64b 100644 --- a/src/template/template_syntax.h +++ b/src/template/template_syntax.h @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,7 +53,7 @@ typedef union YYSTYPE { -/* Line 1685 of yacc.c */ +/* Line 2068 of yacc.c */ #line 74 "template_syntax.y" char * val_str; @@ -62,8 +61,8 @@ typedef union YYSTYPE -/* Line 1685 of yacc.c */ -#line 67 "template_syntax.hh" +/* Line 2068 of yacc.c */ +#line 66 "template_syntax.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/vm/History.cc b/src/vm/History.cc index 3bef2c4eb6..f2a52ccb3c 100644 --- a/src/vm/History.cc +++ b/src/vm/History.cc @@ -43,6 +43,7 @@ History::History( vm_dir(""), hid(-1), vmm_mad_name(""), + vnm_mad_name(""), tm_mad_name(""), stime(0), etime(0), @@ -63,6 +64,7 @@ History::History( const string& _hostname, const string& _vm_dir, const string& _vmm, + const string& _vnm, const string& _tm): oid(_oid), seq(_seq), @@ -70,6 +72,7 @@ History::History( vm_dir(_vm_dir), hid(_hid), vmm_mad_name(_vmm), + vnm_mad_name(_vnm), tm_mad_name(_tm), stime(0), etime(0), @@ -267,6 +270,7 @@ string& History::to_xml(string& xml) const "" << stime << "" << "" << etime << "" << "" << vmm_mad_name << ""<< + "" << vnm_mad_name << ""<< "" << tm_mad_name << "" << "" << prolog_stime << ""<< "" << prolog_etime << ""<< @@ -297,6 +301,7 @@ int History::rebuild_attributes() rc += xpath(stime , "/HISTORY/STIME", 0); rc += xpath(etime , "/HISTORY/ETIME", 0); rc += xpath(vmm_mad_name , "/HISTORY/VMMMAD", "not_found"); + rc += xpath(vnm_mad_name , "/HISTORY/VNMMAD", "not_found"); rc += xpath(tm_mad_name , "/HISTORY/TMMAD", "not_found"); rc += xpath(prolog_stime , "/HISTORY/PSTIME", 0); rc += xpath(prolog_etime , "/HISTORY/PETIME", 0); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index c3737af3fd..1180c0ef93 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -581,6 +581,7 @@ void VirtualMachine::add_history( const string& hostname, const string& vm_dir, const string& vmm_mad, + const string& vnm_mad, const string& tm_mad) { ostringstream os; @@ -597,7 +598,7 @@ void VirtualMachine::add_history( previous_history = history; } - history = new History(oid,seq,hid,hostname,vm_dir,vmm_mad,tm_mad); + history = new History(oid,seq,hid,hostname,vm_dir,vmm_mad,vnm_mad,tm_mad); history_records.push_back(history); }; @@ -620,6 +621,7 @@ void VirtualMachine::cp_history() history->hostname, history->vm_dir, history->vmm_mad_name, + history->vnm_mad_name, history->tm_mad_name); @@ -647,6 +649,7 @@ void VirtualMachine::cp_previous_history() previous_history->hostname, previous_history->vm_dir, previous_history->vmm_mad_name, + previous_history->vnm_mad_name, previous_history->tm_mad_name); previous_history = history; diff --git a/src/vm/test/VirtualMachinePoolTest.cc b/src/vm/test/VirtualMachinePoolTest.cc index 5bcd6c1e7d..10f87c22ff 100644 --- a/src/vm/test/VirtualMachinePoolTest.cc +++ b/src/vm/test/VirtualMachinePoolTest.cc @@ -302,6 +302,7 @@ public: string hostnames[] = {"A_hostname", "B_hostname", "C_hostname"}; string vm_dirs[] = {"A_vm_dir", "B_vm_dir", "C_vm_dir"}; string vmm_mads[] = {"A_vmm_mad", "B_vmm_mad", "C_vmm_mad"}; + string vnm_mads[] = {"A_vnm_mad", "B_vnm_mad", "C_vnm_mad"}; string tm_mads[] = {"A_tm_mad", "B_tm_mad", "C_tm_mad"}; int oid, rc; @@ -324,7 +325,7 @@ public: CPPUNIT_ASSERT( vm != 0 ); // Add a history item - vm->add_history(0, hostnames[0], vm_dirs[0], vmm_mads[0], tm_mads[0]); + vm->add_history(0, hostnames[0], vm_dirs[0], vmm_mads[0], vnm_mads[0], tm_mads[0]); rc = vmp->update(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -342,7 +343,7 @@ public: CPPUNIT_ASSERT( vm != 0 ); // Add a history item - vm->add_history(1, hostnames[1], vm_dirs[1], vmm_mads[1], tm_mads[1]); + vm->add_history(1, hostnames[1], vm_dirs[1], vmm_mads[1], vnm_mads[1], tm_mads[1]); rc = vmp->update(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -351,7 +352,7 @@ public: CPPUNIT_ASSERT( rc == 0 ); // Add another history item - vm->add_history(2, hostnames[2], vm_dirs[2], vmm_mads[2], tm_mads[2]); + vm->add_history(2, hostnames[2], vm_dirs[2], vmm_mads[2], vnm_mads[2], tm_mads[2]); rc = vmp->update(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -408,6 +409,7 @@ public: string new_hostname = "new_hostname"; string vm_dir = "vm_dir"; string vmm_mad = "vm_mad"; + string vnm_mad = "vn_mad"; string tm_mad = "tm_mad"; // Allocate a VM @@ -418,7 +420,7 @@ public: CPPUNIT_ASSERT( vm != 0 ); // Add a history item - vm->add_history(0, hostname, vm_dir, vmm_mad, tm_mad); + vm->add_history(0, hostname, vm_dir, vmm_mad, vnm_mad, tm_mad); rc = vmp->update(vm); CPPUNIT_ASSERT( rc == 0 ); @@ -426,7 +428,7 @@ public: rc = vmp->update_history(vm); CPPUNIT_ASSERT( rc == 0 ); - vm->add_history(0, new_hostname, vm_dir, vmm_mad, tm_mad); + vm->add_history(0, new_hostname, vm_dir, vmm_mad, vnm_mad, tm_mad); rc = vmp->update(vm); CPPUNIT_ASSERT( rc == 0 ); diff --git a/src/vm/vm_var_syntax.cc b/src/vm/vm_var_syntax.cc index 30866385ae..6a75d06320 100644 --- a/src/vm/vm_var_syntax.cc +++ b/src/vm/vm_var_syntax.cc @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.3" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -74,7 +73,7 @@ /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 17 "vm_var_syntax.y" #include @@ -307,7 +306,7 @@ void get_network_attribute(VirtualMachine * vm, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -/* + void get_user_attribute(VirtualMachine * vm, const string& attr_name, string& attr_value) @@ -337,7 +336,7 @@ void get_user_attribute(VirtualMachine * vm, user->unlock(); } -*/ + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -408,6 +407,19 @@ void insert_vector(VirtualMachine * vm, return; } + else if (name == "USER") + { + string value; + + get_user_attribute(vm, vname, value); + + if (!value.empty()) + { + parsed << value; + } + + return; + } else { if ( ( num = vm->get_template_attribute(name.c_str(),values) ) <= 0 ) @@ -447,8 +459,8 @@ void insert_vector(VirtualMachine * vm, -/* Line 189 of yacc.c */ -#line 452 "vm_var_syntax.cc" +/* Line 268 of yacc.c */ +#line 464 "vm_var_syntax.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -493,8 +505,8 @@ void insert_vector(VirtualMachine * vm, typedef union YYSTYPE { -/* Line 214 of yacc.c */ -#line 395 "vm_var_syntax.y" +/* Line 293 of yacc.c */ +#line 408 "vm_var_syntax.y" char * val_str; int val_int; @@ -502,8 +514,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 507 "vm_var_syntax.cc" +/* Line 293 of yacc.c */ +#line 519 "vm_var_syntax.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -527,8 +539,8 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 532 "vm_var_syntax.cc" +/* Line 343 of yacc.c */ +#line 544 "vm_var_syntax.cc" #ifdef short # undef short @@ -631,11 +643,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -658,24 +670,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -706,23 +718,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -742,6 +738,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 7 /* YYLAST -- Last index in YYTABLE. */ @@ -814,7 +830,7 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 419, 419, 420, 423, 427, 440, 455 + 0, 432, 432, 433, 436, 440, 453, 468 }; #endif @@ -851,8 +867,8 @@ static const yytype_uint8 yyr2[] = 0, 2, 1, 2, 1, 2, 5, 9 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -883,8 +899,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -892,6 +907,12 @@ static const yytype_uint8 yytable[] = 2, 12, 13, 14, 15, 16, 8, 0, 17 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-5)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_int8 yycheck[] = { 0, 5, 4, 7, 6, -1, 9, 10, 9, 9, @@ -939,7 +960,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -1207,7 +1227,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1310,115 +1329,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1461,6 +1507,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, mc, vm, parsed, errmsg) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1477,12 +1524,9 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1698,7 +1742,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1729,8 +1773,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1786,17 +1830,17 @@ yyreduce: { case 4: -/* Line 1464 of yacc.c */ -#line 424 "vm_var_syntax.y" +/* Line 1806 of yacc.c */ +#line 437 "vm_var_syntax.y" { (*parsed) << (yyvsp[(1) - (1)].val_str); - ;} + } break; case 5: -/* Line 1464 of yacc.c */ -#line 428 "vm_var_syntax.y" +/* Line 1806 of yacc.c */ +#line 441 "vm_var_syntax.y" { string name((yyvsp[(1) - (2)].val_str)); @@ -1808,13 +1852,13 @@ yyreduce: { (*parsed) << (yyvsp[(2) - (2)].val_char); } - ;} + } break; case 6: -/* Line 1464 of yacc.c */ -#line 441 "vm_var_syntax.y" +/* Line 1806 of yacc.c */ +#line 454 "vm_var_syntax.y" { string name((yyvsp[(1) - (5)].val_str)); string vname((yyvsp[(3) - (5)].val_str)); @@ -1828,13 +1872,13 @@ yyreduce: { (*parsed) << (yyvsp[(5) - (5)].val_char); } - ;} + } break; case 7: -/* Line 1464 of yacc.c */ -#line 456 "vm_var_syntax.y" +/* Line 1806 of yacc.c */ +#line 469 "vm_var_syntax.y" { string name((yyvsp[(1) - (9)].val_str)); string vname((yyvsp[(3) - (9)].val_str)); @@ -1851,15 +1895,26 @@ yyreduce: { (*parsed) << (yyvsp[(9) - (9)].val_char); } - ;} + } break; -/* Line 1464 of yacc.c */ -#line 1861 "vm_var_syntax.cc" +/* Line 1806 of yacc.c */ +#line 1905 "vm_var_syntax.cc" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1888,6 +1943,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1895,37 +1954,36 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (&yylloc, mc, vm, parsed, errmsg, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, mc, vm, parsed, errmsg, yymsg); - } - else - { - yyerror (&yylloc, mc, vm, parsed, errmsg, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, mc, vm, parsed, errmsg, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1985,7 +2043,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -2049,8 +2107,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, mc, vm, parsed, errmsg); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, mc, vm, parsed, errmsg); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2075,8 +2138,8 @@ yyreturn: -/* Line 1684 of yacc.c */ -#line 474 "vm_var_syntax.y" +/* Line 2067 of yacc.c */ +#line 487 "vm_var_syntax.y" extern "C" void vm_var__error( diff --git a/src/vm/vm_var_syntax.h b/src/vm/vm_var_syntax.h index 8d099c1d0a..d40f8d1d51 100644 --- a/src/vm/vm_var_syntax.h +++ b/src/vm/vm_var_syntax.h @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,8 +55,8 @@ typedef union YYSTYPE { -/* Line 1685 of yacc.c */ -#line 395 "vm_var_syntax.y" +/* Line 2068 of yacc.c */ +#line 408 "vm_var_syntax.y" char * val_str; int val_int; @@ -65,8 +64,8 @@ typedef union YYSTYPE -/* Line 1685 of yacc.c */ -#line 70 "vm_var_syntax.hh" +/* Line 2068 of yacc.c */ +#line 69 "vm_var_syntax.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/vm/vm_var_syntax.y b/src/vm/vm_var_syntax.y index ae83471f07..bd75e41a02 100644 --- a/src/vm/vm_var_syntax.y +++ b/src/vm/vm_var_syntax.y @@ -245,7 +245,7 @@ void get_network_attribute(VirtualMachine * vm, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -/* + void get_user_attribute(VirtualMachine * vm, const string& attr_name, string& attr_value) @@ -275,7 +275,7 @@ void get_user_attribute(VirtualMachine * vm, user->unlock(); } -*/ + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -346,6 +346,19 @@ void insert_vector(VirtualMachine * vm, return; } + else if (name == "USER") + { + string value; + + get_user_attribute(vm, vname, value); + + if (!value.empty()) + { + parsed << value; + } + + return; + } else { if ( ( num = vm->get_template_attribute(name.c_str(),values) ) <= 0 ) diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index fc43d3380f..94706f35f8 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -245,12 +245,80 @@ void VirtualMachineManager::do_action(const string &action, void * arg) /* Manager Actions */ /* ************************************************************************** */ +string * VirtualMachineManager::format_message( + const string& hostname, + const string& net_drv, + const string& m_hostname, + const string& m_net_drv, + const string& domain, + const string& ldfile, + const string& rdfile, + const string& cfile, + const string& tmpl) +{ + ostringstream oss; + + oss << "" + << "" << hostname << "" + << "" << net_drv << ""; + + if (!m_hostname.empty()) + { + oss << "" << m_hostname << "" + << ""<< m_net_drv << ""; + } + else + { + oss << ""; + } + + if (!domain.empty()) + { + oss << "" << domain << ""; + } + else + { + oss << ""; + } + + if (!ldfile.empty()) + { + oss << "" << ldfile << ""; + oss << "" << rdfile << ""; + } + else + { + oss << ""; + oss << ""; + } + + if (!cfile.empty()) + { + oss << "" << cfile << ""; + } + else + { + oss << ""; + } + + oss << tmpl + << ""; + + return SSLTools::base64_encode(oss.str()); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void VirtualMachineManager::deploy_action(int vid) { - VirtualMachine * vm; - const VirtualMachineManagerDriver * vmd; - int rc; - ostringstream os; + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + int rc; + + ostringstream os; + string vm_tmpl; + string * drv_msg; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -287,7 +355,20 @@ void VirtualMachineManager::deploy_action(int vid) } // Invoke driver method - vmd->deploy(vid,vm->get_hostname(),vm->get_remote_deployment_file()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + "", + vm->get_deployment_file(), + vm->get_remote_deployment_file(), + "", + vm->to_xml(vm_tmpl)); + + vmd->deploy(vid, *drv_msg); + + delete drv_msg; vm->unlock(); @@ -326,8 +407,11 @@ void VirtualMachineManager::save_action( { VirtualMachine * vm; const VirtualMachineManagerDriver * vmd; - string hostname; - ostringstream os; + + string hostname, vnm_mad; + string vm_tmpl; + string * drv_msg; + ostringstream os; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -359,20 +443,32 @@ void VirtualMachineManager::save_action( } hostname = vm->get_previous_hostname(); + vnm_mad = vm->get_previous_vnm_mad(); } else { - hostname=vm->get_hostname(); + hostname = vm->get_hostname(); + vnm_mad = vm->get_vnm_mad(); } // Invoke driver method - vmd->save( - vid, + drv_msg = format_message( hostname, + vnm_mad, + "", + "", vm->get_deploy_id(), - vm->get_checkpoint_file()); + "", + "", + vm->get_checkpoint_file(), + vm->to_xml(vm_tmpl)); + + vmd->save(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -406,9 +502,12 @@ error_common: void VirtualMachineManager::shutdown_action( int vid) { - VirtualMachine * vm; - const VirtualMachineManagerDriver * vmd; - ostringstream os; + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + string vm_tmpl; + string * drv_msg; + ostringstream os; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -432,9 +531,23 @@ void VirtualMachineManager::shutdown_action( } // Invoke driver method - vmd->shutdown(vid,vm->get_hostname(),vm->get_deploy_id()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->shutdown(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -466,6 +579,9 @@ void VirtualMachineManager::cancel_action( VirtualMachine * vm; ostringstream os; + string vm_tmpl; + string * drv_msg; + const VirtualMachineManagerDriver * vmd; // Get the VM from the pool @@ -490,9 +606,23 @@ void VirtualMachineManager::cancel_action( } // Invoke driver method - vmd->cancel(vid,vm->get_hostname(),vm->get_deploy_id()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->cancel(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -527,6 +657,9 @@ void VirtualMachineManager::cancel_previous_action( VirtualMachine * vm; ostringstream os; + string vm_tmpl; + string * drv_msg; + const VirtualMachineManagerDriver * vmd; // Get the VM from the pool @@ -551,9 +684,23 @@ void VirtualMachineManager::cancel_previous_action( } // Invoke driver method - vmd->cancel(vid,vm->get_previous_hostname(),vm->get_deploy_id()); + drv_msg = format_message( + vm->get_previous_hostname(), + vm->get_previous_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->cancel(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -579,7 +726,10 @@ void VirtualMachineManager::migrate_action( { VirtualMachine * vm; const VirtualMachineManagerDriver * vmd; - ostringstream os; + + ostringstream os; + string vm_tmpl; + string * drv_msg; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -608,10 +758,20 @@ void VirtualMachineManager::migrate_action( } // Invoke driver method - vmd->migrate(vid, - vm->get_previous_hostname(), - vm->get_deploy_id(), - vm->get_hostname()); + drv_msg = format_message( + vm->get_previous_hostname(), + vm->get_previous_vnm_mad(), + vm->get_hostname(), + vm->get_vnm_mad(), + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->migrate(vid, *drv_msg); + + delete drv_msg; vm->unlock(); @@ -648,9 +808,13 @@ error_common: void VirtualMachineManager::restore_action( int vid) { - VirtualMachine * vm; - const VirtualMachineManagerDriver * vmd; - ostringstream os; + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os; + + string vm_tmpl; + string * drv_msg; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -674,12 +838,23 @@ void VirtualMachineManager::restore_action( } // Invoke driver method - vmd->restore(vid, - vm->get_hostname(), - vm->get_deploy_id(), - vm->get_checkpoint_file()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + vm->get_checkpoint_file(), + vm->to_xml(vm_tmpl)); + + vmd->restore(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -708,9 +883,13 @@ error_common: void VirtualMachineManager::poll_action( int vid) { - VirtualMachine * vm; - const VirtualMachineManagerDriver * vmd; - ostringstream os; + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os; + + string vm_tmpl; + string * drv_msg; // Get the VM from the pool vm = vmpool->get(vid,true); @@ -734,9 +913,23 @@ void VirtualMachineManager::poll_action( } // Invoke driver method - vmd->poll(vid,vm->get_hostname(),vm->get_deploy_id()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->poll(vid, *drv_msg); + + delete drv_msg; vm->unlock(); + return; error_history: @@ -824,6 +1017,9 @@ void VirtualMachineManager::timer_action() const VirtualMachineManagerDriver * vmd; + string vm_tmpl; + string * drv_msg; + mark = mark + timer_period; if ( mark >= 600 ) @@ -874,7 +1070,20 @@ void VirtualMachineManager::timer_action() continue; } - vmd->poll(*it,vm->get_hostname(),vm->get_deploy_id()); + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->poll(*it, *drv_msg); + + delete drv_msg; vmpool->update(vm); diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc index 4b58f06f2f..d20db0f5e0 100644 --- a/src/vmm/VirtualMachineManagerDriver.cc +++ b/src/vmm/VirtualMachineManagerDriver.cc @@ -104,13 +104,12 @@ void VirtualMachineManagerDriver::get_default( void VirtualMachineManagerDriver::deploy ( const int oid, - const string& host, - const string& conf) const + const string& drv_msg) const { ostringstream os; - os << "DEPLOY " << oid << " " << host << " " << conf << " -" << endl; - + os << "DEPLOY " << oid << " " << drv_msg << endl; + write(os); }; @@ -119,12 +118,11 @@ void VirtualMachineManagerDriver::deploy ( void VirtualMachineManagerDriver::shutdown ( const int oid, - const string& host, - const string& name) const + const string& drv_msg) const { ostringstream os; - os << "SHUTDOWN " << oid << " " << host << " " << name << " -" << endl; + os << "SHUTDOWN " << oid << " " << drv_msg << endl; write(os); }; @@ -134,12 +132,11 @@ void VirtualMachineManagerDriver::shutdown ( void VirtualMachineManagerDriver::cancel ( const int oid, - const string& host, - const string& name) const + const string& drv_msg) const { ostringstream os; - os << "CANCEL " << oid << " " << host << " " << name << " -" << endl; + os << "CANCEL " << oid << " " << drv_msg << endl; write(os); }; @@ -149,13 +146,11 @@ void VirtualMachineManagerDriver::cancel ( void VirtualMachineManagerDriver::checkpoint ( const int oid, - const string& host, - const string& name, - const string& file) const + const string& drv_msg) const { ostringstream os; - os<< "CHECKPOINT " << oid<< " "<< host<< " "<< name<< " "<< file<< endl; + os<< "CHECKPOINT " << oid << " " << drv_msg << endl; write(os); }; @@ -165,13 +160,11 @@ void VirtualMachineManagerDriver::checkpoint ( void VirtualMachineManagerDriver::save ( const int oid, - const string& host, - const string& name, - const string& file) const + const string& drv_msg) const { ostringstream os; - os<< "SAVE " << oid << " " << host << " " << name << " "<< file << endl; + os<< "SAVE " << oid << " " << drv_msg << endl; write(os); }; @@ -181,13 +174,11 @@ void VirtualMachineManagerDriver::save ( void VirtualMachineManagerDriver::restore ( const int oid, - const string& host, - const string& name, - const string& file) const + const string& drv_msg) const { ostringstream os; - os << "RESTORE " << oid << " " << host << " " << name << " " << file<< endl; + os << "RESTORE " << oid << " " << drv_msg << endl; write(os); }; @@ -197,13 +188,11 @@ void VirtualMachineManagerDriver::restore ( void VirtualMachineManagerDriver::migrate ( const int oid, - const string& shost, - const string& name, - const string& dhost) const + const string& drv_msg) const { ostringstream os; - os<< "MIGRATE " << oid << " "<< shost<< " "<< name<< " "<< dhost<< endl; + os<< "MIGRATE " << oid << " " << drv_msg << endl; write(os); }; @@ -213,12 +202,11 @@ void VirtualMachineManagerDriver::migrate ( void VirtualMachineManagerDriver::poll ( const int oid, - const string& host, - const string& name) const + const string& drv_msg) const { ostringstream os; - os << "POLL " << oid << " " << host << " " << name << " -" << endl; + os << "POLL " << oid << " " << drv_msg << endl; write(os); }; diff --git a/src/vmm/XMLDriver.cc b/src/vmm/XMLDriver.cc index 2879211e64..4329b71f30 100644 --- a/src/vmm/XMLDriver.cc +++ b/src/vmm/XMLDriver.cc @@ -35,9 +35,7 @@ int XMLDriver::deployment_description( return -1; } - vm->template_to_xml(xml); - - file << xml ; + file << vm->template_to_xml(xml); file.close(); diff --git a/src/vmm_mad/dummy/one_vmm_dummy.rb b/src/vmm_mad/dummy/one_vmm_dummy.rb index 1d7b84470b..f424a12c13 100755 --- a/src/vmm_mad/dummy/one_vmm_dummy.rb +++ b/src/vmm_mad/dummy/one_vmm_dummy.rb @@ -39,31 +39,36 @@ class DummyDriver < VirtualMachineDriver ) end - def deploy(id, host, remote_dfile, not_used) - send_message(ACTION[:deploy],RESULT[:success],id,"dummy") + def deploy(id, drv_message) + msg = decode(drv_message) + + host = msg.elements["HOST"].text + name = msg.elements["VM/NAME"].text + + send_message(ACTION[:deploy],RESULT[:success],id,"#{host}:#{name}:dummy") end - def shutdown(id, host, deploy_id, not_used) + def shutdown(id, drv_message) send_message(ACTION[:shutdown],RESULT[:success],id) end - def cancel(id, host, deploy_id, not_used) + def cancel(id, drv_message) send_message(ACTION[:cancel],RESULT[:success],id) end - def save(id, host, deploy_id, file) + def save(id, drv_message) send_message(ACTION[:save],RESULT[:success],id) end - def restore(id, host, deploy_id , file) + def restore(id, drv_message) send_message(ACTION[:restore],RESULT[:success],id) end - def migrate(id, host, deploy_id, dest_host) + def migrate(id, drv_message) send_message(ACTION[:migrate],RESULT[:success],id) end - def poll(id, host, deploy_id, not_used) + def poll(id, drv_message) # monitor_info: string in the form "VAR=VAL VAR=VAL ... VAR=VAL" # known VAR are in POLL_ATTRIBUTES. VM states VM_STATES monitor_info = "#{POLL_ATTRIBUTE[:state]}=#{VM_STATE[:active]} " \ diff --git a/src/vmm_mad/ec2/one_vmm_ec2.rb b/src/vmm_mad/ec2/one_vmm_ec2.rb index 10441c1115..f5346e58f9 100755 --- a/src/vmm_mad/ec2/one_vmm_ec2.rb +++ b/src/vmm_mad/ec2/one_vmm_ec2.rb @@ -89,9 +89,12 @@ class EC2Driver < VirtualMachineDriver end # DEPLOY action, also sets ports and ip if needed - def deploy(id, host, remote_dfile, not_used) + def deploy(id, drv_message) + msg = decode(drv_message) - local_dfile = get_local_deployment_file(remote_dfile) + host = msg.elements["HOST"].text + + local_dfile = msg.elements["LOCAL_DEPLOYMENT_FILE"].text if !local_dfile send_message(ACTION[:deploy],RESULT[:failure],id, @@ -175,17 +178,31 @@ class EC2Driver < VirtualMachineDriver end # Shutdown a EC2 instance - def shutdown(id, host, deploy_id, not_used) + def shutdown(id, drv_message) + msg = decode(drv_message) + + host = msg.elements["HOST"].text + deploy_id = msg.elements["DEPLOY_ID"].text + ec2_terminate(ACTION[:shutdown], id, deploy_id) end # Cancel a EC2 instance - def cancel(id, host, deploy_id, not_used) + def cancel(id, drv_message) + msg = decode(drv_message) + + host = msg.elements["HOST"].text + deploy_id = msg.elements["DEPLOY_ID"].text + ec2_terminate(ACTION[:cancel], id, deploy_id) end # Get info (IP, and state) for a EC2 instance - def poll(id, host, deploy_id, not_used) + def poll(id, drv_message) + msg = decode(drv_message) + + host = msg.elements["HOST"].text + deploy_id = msg.elements["DEPLOY_ID"].text info = "#{POLL_ATTRIBUTE[:usedmemory]}=0 " \ "#{POLL_ATTRIBUTE[:usedcpu]}=0 " \ diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index fff1872265..b16867ee56 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -16,7 +16,6 @@ # limitations under the License. # #--------------------------------------------------------------------------- # - # Set up the environment for the driver ONE_LOCATION = ENV["ONE_LOCATION"] @@ -32,12 +31,188 @@ end $: << RUBY_LIB_LOCATION require "VirtualMachineDriver" +require 'one_vnm' require 'getoptlong' +require 'ssh_stream' + +require 'pp' + +class VmmAction + attr_reader :data + + # Initialize a VmmAction object + # @param[OpenNebula::ExecDriver] Driver to be used for the actions + # @param[String] Id of the VM + # @param[String] name of the actions as described in the VMM protocol + # @param[xml_data] data sent from OpenNebula core + def initialize(driver, id, action, xml_data) + # Initialize object with xml data + @vmm = driver + @id = id + + @main_action = action + @xml_data = @vmm.decode(xml_data) + + @data = Hash.new + + get_data(:host) + get_data(:net_drv) + get_data(:deploy_id) + get_data(:checkpoint_file) + + get_data(:local_dfile, :LOCAL_DEPLOYMENT_FILE) + get_data(:remote_dfile, :REMOTE_DEPLOYMENT_FILE) + + # For migration + get_data(:dest_host, :MIGR_HOST) + get_data(:dest_driver, :MIGR_NET_DRV) + + # Initialize streams and vnm + @ssh_src = @vmm.get_ssh_stream(@data[:host], @id) + @vnm_src = VirtualNetworkDriver.new(@data[:net_drv], + :local_actions => @vmm.options[:local_actions], + :message => @xml_data, + :ssh_stream => @ssh_src) + + if @data[:dest_host] and !@data[:dest_host].empty? + @ssh_dst = @vmm.get_ssh_stream(@data[:dest_host], @id) + @vnm_dst = VirtualNetworkDriver.new(@data[:dest_driver], + :local_actions => @vmm.options[:local_actions], + :message => @xml_data, + :ssh_stream => @ssh_dst) + end + end + + #Execute a set of steps defined with + # - :driver :vmm or :vnm to execute the step + # - :action for the step + # - :parameters command line paremeters for the action + # - :destination use next host + # - :fail_action steps to be executed if steps fail + # - :stdin for the action + # @param [Array] of steps + def run(steps, info_on_success = nil) + result = execute_steps(steps) + + #Prepare the info for the OpenNebula core + if DriverExecHelper.failed?(result) + info = @data[:failed_info] + else + info = @data["#{@main_action.to_s}_info".to_sym] + end + + @vmm.send_message(VirtualMachineDriver::ACTION[@main_action], + result, @id, info) + end + + private + + DRIVER_NAMES = { + :vmm => "virtualization driver", + :vnm => "network driver" + } + + # Executes a set of steps. If one step fails any recover action is performed + # and the step execution breaks. + # @param [Array] array of steps to be executed + # @return [String, Hash] "SUCCESS/FAILURE" for the step set, and + # information associated to each step (by :_info). In case of + # failure information is also in [:failed_info] + def execute_steps(steps) + result = DriverExecHelper.const_get(:RESULT)[:failure] + + steps.each do |step| + # Execute Step + case step[:driver] + when :vmm + if step[:destination] + host = @data[:dest_host] + ssh = @ssh_dst + else + host = @data[:host] + ssh = @ssh_src + end + + result, info = @vmm.do_action(get_parameters(step[:parameters]), + @id, + host, + step[:action], + :ssh_stream => ssh, + :respond => false, + :stdin => step[:stdin]) + when :vnm + if step[:destination] + vnm = @vnm_dst + else + vnm = @vnm_src + end + + result, info = vnm.do_action(@id, step[:action]) + else + result = DriverExecHelper.const_get(:RESULT)[:failure] + info = "No driver in #{step[:action]}" + end + + # Save the step info + @data["#{step[:action]}_info".to_sym] = info + + # Roll back steps, store failed info and break steps + if DriverExecHelper.failed?(result) + execute_steps(@data[:fail_actions]) if @data[:fail_actions] + @data[:failed_info] = info + + @vmm.log(@id, + "Failed to execute #{DRIVER_NAMES[step[:driver]]} " \ + "operation: #{step[:action]}.") + break + else + @vmm.log(@id, + "Sussecfully execute #{DRIVER_NAMES[step[:driver]]} " \ + "operation: #{step[:action]}.") + end + end + + return result + end + + # Prepare the parameters for the action step generating a blanck separated + # list of command arguments + # @param [Hash] an action step + def get_parameters(step_params) + parameters = step_params || [] + + parameters.map do |param| + if Symbol===param + @data[param].to_s + else + param + end + end.join(' ') + end + + # Extracts data from the XML argument of the VMM action + # @param [Symbol] corresponding to a XML element + # @param [String] an xpath for the XML element + # @return [String] the element value + def get_data(name, xml_path=nil) + if xml_path + path=xml_path.to_s + else + path=name.to_s.upcase + end + + @data[name]=@xml_data.elements[path].text + end +end + # The main class for the Sh driver class ExecDriver < VirtualMachineDriver + attr_reader :options - # SshDriver constructor + # Initializes the VMM driver + # @param [String] hypervisor name identifies the plugin + # @param [OpenNebulaDriver::options] def initialize(hypervisor, options={}) @options={ :threaded => true @@ -48,9 +223,29 @@ class ExecDriver < VirtualMachineDriver @hypervisor = hypervisor end + # Creates an SshStream to execute commands on the target host + # @param[String] the hostname of the host + # @param[String] id of the VM to log messages + # @return [SshStreamCommand] + def get_ssh_stream(host, id) + SshStreamCommand.new(host, + @remote_scripts_base_path, + log_method(id)) + end + + #--------------------------------------------------------------------------- + # Virtual Machine Manager Protocol Actions + #--------------------------------------------------------------------------- + # # DEPLOY action, sends the deployment file to remote host - def deploy(id, host, remote_dfile, not_used) - local_dfile = get_local_deployment_file(remote_dfile) + # + def deploy(id, drv_message) + action = VmmAction.new(self, id, :deploy, drv_message) + + # ---------------------------------------------------------------------- + # Initialization of deployment data + # ---------------------------------------------------------------------- + local_dfile=action.data[:local_dfile] if !local_dfile || File.zero?(local_dfile) send_message(ACTION[:deploy],RESULT[:failure],id, @@ -58,48 +253,207 @@ class ExecDriver < VirtualMachineDriver return end - tmp = File.new(local_dfile) - domain = tmp.read - tmp.close() + domain = File.read(local_dfile) if action_is_local?(:deploy) - dfile=local_dfile + dfile = action.data[:local_dfile] else - dfile=remote_dfile + dfile = action.data[:remote_dfile] end - do_action("#{dfile} #{host}", id, host, :deploy, - :stdin => domain) + # ---------------------------------------------------------------------- + # Deployment Steps + # ---------------------------------------------------------------------- + + steps=[ + # Execute pre-boot networking setup + { + :driver => :vnm, + :action => :pre + }, + # Boot the Virtual Machine + { + :driver => :vmm, + :action => :deploy, + :parameters => [dfile, :host], + :stdin => domain + }, + # Execute post-boot networking setup + { + :driver => :vnm, + :action => :post, + :fail_actions => [ + { + :driver => :vmm, + :action => :cancel, + :parameters => [:deploy_info, :host] + } + ] + } + ] + + action.run(steps) end - # Basic Domain Management Operations + # + # SHUTDOWN action, graceful shutdown and network clean up + # + def shutdown(id, drv_message) - def shutdown(id, host, deploy_id, not_used) - do_action("#{deploy_id} #{host}", id, host, :shutdown) + action = VmmAction.new(self, id, :shutdown, drv_message) + + steps=[ + # Shutdown the Virtual Machine + { + :driver => :vmm, + :action => :shutdown, + :parameters => [:deploy_id, :host] + }, + # Execute networking clean up operations + { + :driver => :vnm, + :action => :clean + } + ] + + action.run(steps) end - def cancel(id, host, deploy_id, not_used) - do_action("#{deploy_id} #{host}", id, host, :cancel) + # + # CANCEL action, destroys a VM and network clean up + # + def cancel(id, drv_message) + action = VmmAction.new(self, id, :cancel, drv_message) + + steps=[ + # Cancel the Virtual Machine + { + :driver => :vmm, + :action => :cancel, + :parameters => [:deploy_id, :host] + }, + # Execute networking clean up operations + { + :driver => :vnm, + :action => :clean + } + ] + + action.run(steps) end - def save(id, host, deploy_id, file) - do_action("#{deploy_id} #{file} #{host}", id, host, :save) + # + # SAVE action, stops the VM and saves its state, network is cleaned up + # + def save(id, drv_message) + action = VmmAction.new(self, id, :save, drv_message) + + steps=[ + # Save the Virtual Machine state + { + :driver => :vmm, + :action => :save, + :parameters => [:deploy_id, :checkpoint_file, :host] + }, + # Execute networking clean up operations + { + :driver => :vnm, + :action => :clean + } + ] + + action.run(steps) end - def restore(id, host, deploy_id, file) - do_action("#{file} #{host}", id, host, :restore) + # + # RESTORE action, restore a VM from a previous state, and restores network + # + def restore(id, drv_message) + action=VmmAction.new(self, id, :restore, drv_message) + + steps=[ + # Execute pre-boot networking setup + { + :driver => :vnm, + :action => :pre + }, + # Restore the Virtual Machine from checkpoint + { + :driver => :vmm, + :action => :restore, + :parameters => [:checkpoint_file, :host] + }, + # Execute post-boot networking setup + { + :driver => :vnm, + :action => :post, + :fail_actions => [ + { + :driver => :vmm, + :action => :cancel, + :parameters => [:deploy_id, :host] + } + ], + } + ] + + action.run(steps) end - def migrate(id, host, deploy_id, dest_host) - do_action("#{deploy_id} #{dest_host} #{host}", id, host, :migrate) + # + # MIGRATE (live) action, migrates a VM to another host creating network + # + def migrate(id, drv_message) + action=VmmAction.new(self, id, :migrate, drv_message) + + steps=[ + # Execute pre-boot networking setup on migrating host + { + :driver => :vnm, + :action => :pre, + :destination => true + }, + # Migrate the Virtual Machine + { + :driver => :vmm, + :action => :migrate, + :parameters => [:deploy_id, :dest_host, :host] + }, + # Execute networking clean up operations + { + :driver => :vnm, + :action => :clean + }, + # Execute post-boot networking setup on migrating host + { + :driver => :vnm, + :action => :post, + :destination => :true + #TODO :fail_action what to do here? cancel VM? + }, + ] + + action.run(steps) end - def poll(id, host, deploy_id, not_used) + # + # POLL action, gets information of a VM + # + def poll(id, drv_message) + data = decode(drv_message) + host = data.elements['HOST'].text + deploy_id = data.elements['DEPLOY_ID'].text + do_action("#{deploy_id} #{host}", id, host, :poll) end end -# SshDriver Main program +################################################################################ +# +# Virtual Machine Manager Execution Driver - Main Program +# +################################################################################ + opts = GetoptLong.new( [ '--retries', '-r', GetoptLong::OPTIONAL_ARGUMENT ], [ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ], @@ -138,3 +492,5 @@ exec_driver = ExecDriver.new(hypervisor, :local_actions => local_actions) exec_driver.start_driver + + diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index a1bdb86264..cdb5bde990 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -25,6 +25,8 @@ #include "AuthManager.h" +#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper) + /* ************************************************************************** */ /* Virtual Network :: Constructor/Destructor */ /* ************************************************************************** */ @@ -207,6 +209,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) int rc; string pub; + string vlan_attr; string s_type; unsigned int default_size = VirtualNetworkPool::default_size(); @@ -219,7 +222,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) // ------------ TYPE ---------------------- erase_template_attribute("TYPE",s_type); - transform(s_type.begin(),s_type.end(),s_type.begin(),(int(*)(int))toupper); + TO_UPPER(s_type); if (s_type == "RANGED") { @@ -255,6 +258,14 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) erase_template_attribute("VLAN_ID",vlan_id); + // ------------ VLAN ---------------------- + + erase_template_attribute("VLAN", vlan_attr); + + TO_UPPER(vlan_attr); + + vlan = (vlan_attr == "YES"); + // ------------ BRIDGE -------------------- erase_template_attribute("BRIDGE",bridge); @@ -272,7 +283,6 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) oss << "onebr" << oid; bridge = oss.str(); - replace_template_attribute("BRIDGE",bridge); } } @@ -280,7 +290,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) erase_template_attribute("PUBLIC", pub); - transform (pub.begin(), pub.end(), pub.begin(), (int(*)(int))toupper); + TO_UPPER(pub); public_obj = (pub == "YES"); @@ -515,7 +525,8 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const "" << gname << "" << "" << name << "" << "" << type << "" << - "" << bridge << ""; + "" << bridge << ""<< + "" << vlan << ""; if (!phydev.empty()) { @@ -583,6 +594,7 @@ int VirtualNetwork::from_xml(const string &xml_str) rc += xpath(int_type, "/VNET/TYPE", -1); rc += xpath(bridge, "/VNET/BRIDGE", "not_found"); rc += xpath(public_obj, "/VNET/PUBLIC", 0); + rc += xpath(vlan, "/VNET/VLAN", 0); xpath(phydev, "/VNET/PHYDEV", ""); xpath(vlan_id, "/VNET/VLAN_ID",""); @@ -653,6 +665,15 @@ int VirtualNetwork::nic_attribute(VectorAttribute *nic, int vid) nic->replace("MAC" ,mac); nic->replace("IP" ,ip); + if ( vlan == 1 ) + { + nic->replace("VLAN", "YES"); + } + else + { + nic->replace("VLAN", "NO"); + } + if (!phydev.empty()) { nic->replace("PHYDEV", phydev); diff --git a/src/vnm/test/VirtualNetworkPoolTest.cc b/src/vnm/test/VirtualNetworkPoolTest.cc index 2d5801309c..7cf06211be 100644 --- a/src/vnm/test/VirtualNetworkPoolTest.cc +++ b/src/vnm/test/VirtualNetworkPoolTest.cc @@ -71,18 +71,18 @@ const string templates[] = const string xmls[] = { - "01230the_useroneadminNet number one1br100130.10.0.150:20:20:20:20:200-1", + "01230the_useroneadminNet number one1br1000130.10.0.150:20:20:20:20:200-1", - "12610the_useroneadminA virtual network0br010", + "12610the_useroneadminA virtual network0br0010", - "01330the_useroneadminNet number two1br100130.10.2.150:20:20:20:20:200-1", + "01330the_useroneadminNet number two1br1000130.10.2.150:20:20:20:20:200-1", }; const string xml_dump = - "010the_useroneadminNet number one1br100120the_useroneadminA virtual network0br010"; + "010the_useroneadminNet number one1br1000120the_useroneadminA virtual network0br0010"; const string xml_dump_where = - "120the_useroneadminA virtual network0br010"; + "120the_useroneadminA virtual network0br0010"; /* ************************************************************************* */ /* ************************************************************************* */ @@ -310,8 +310,8 @@ public: }; string phydev_xml[] = { - "000the_useroneadminBRIDGE and PHYDEV1br0eth000130.10.0.150:20:20:20:20:200-1", - "100the_useroneadminNo BRIDGE only PHYDEV1onebr1eth000130.10.0.150:20:20:20:20:200-1" + "000the_useroneadminBRIDGE and PHYDEV1br00eth000130.10.0.150:20:20:20:20:200-1", + "100the_useroneadminNo BRIDGE only PHYDEV1onebr10eth000130.10.0.150:20:20:20:20:200-1" }; // test vm with bridge and phydev diff --git a/src/vnm_mad/one_vnm.rb b/src/vnm_mad/one_vnm.rb new file mode 100644 index 0000000000..aba0339611 --- /dev/null +++ b/src/vnm_mad/one_vnm.rb @@ -0,0 +1,70 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +require "DriverExecHelper" + +# This module provides an abstraction to generate an execution context for +# OpenNebula Drivers + +class VirtualNetworkDriver + include DriverExecHelper + + # Inits the VNET Driver + # @param [String] name of the vnet driver to use, as listed in remotes/vnet + # @option ops [String] :ssh_stream to be used for command execution + # @option ops [String] :message from ONE + def initialize(directory, options={}) + + @options = options + @ssh_stream = options[:ssh_stream] + @message = options[:message] + + @vm_encoded = Base64.encode64(@message.elements['VM'].to_s).delete("\n") + + initialize_helper("vnm/#{directory}", options) + end + + # Calls remotes or local action checking the action name and + # @local_actions. Optional arguments can be specified as a hash + # + # @param [Number, String] id action identifier + # @param [String, Symbol] aname name of the action + # @param [Hash] ops extra options for the command + # @option ops [String] :stdin text to be writen to stdin + def do_action(id, aname, ops = {}) + options={ + :stdin => nil, + }.merge(ops) + + cmd = action_command_line(aname, @vm_encoded) + + if action_is_local?(aname) + execution = LocalCommand.run(cmd, log_method(id)) + else + if options[:stdin] + cmdin = "cat << EOT | #{cmd}" + stdin = "#{options[:stdin]}\nEOT\n" + else + cmdin = cmd + stdin = nil + end + + execution = @ssh_stream.run(cmdin, stdin, cmd) + end + + result, info = get_info_from_execution(execution) + end +end \ No newline at end of file diff --git a/src/vnm_mad/HostManaged.rb b/src/vnm_mad/remotes/802.1Q/HostManaged.rb similarity index 87% rename from src/vnm_mad/HostManaged.rb rename to src/vnm_mad/remotes/802.1Q/HostManaged.rb index bda6286ef1..47a65a3cce 100644 --- a/src/vnm_mad/HostManaged.rb +++ b/src/vnm_mad/remotes/802.1Q/HostManaged.rb @@ -14,6 +14,8 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'OpenNebulaNetwork' + class OpenNebulaHM < OpenNebulaNetwork def initialize(vm, hypervisor = nil) super(vm,hypervisor) @@ -48,12 +50,8 @@ class OpenNebulaHM < OpenNebulaNetwork end end end - end - def deactivate - vm_id = @vm['ID'] - process do |nic| - end + return 0 end def bridge_exists?(bridge) @@ -61,16 +59,16 @@ class OpenNebulaHM < OpenNebulaNetwork end def create_bridge(bridge) - system("#{COMMANDS[:brctl]} addbr #{bridge}") + OpenNebula.exec_and_log("#{COMMANDS[:brctl]} addbr #{bridge}") end def device_exists?(dev, vlan=nil) dev = "#{dev}.#{vlan}" if vlan - system("#{COMMANDS[:ip]} link show #{dev}") + OpenNebula.exec_and_log("#{COMMANDS[:ip]} link show #{dev}") end def create_dev_vlan(dev, vlan) - system("#{COMMANDS[:vconfig]} add #{dev} #{vlan}") + OpenNebula.exec_and_log("#{COMMANDS[:vconfig]} add #{dev} #{vlan}") end def attached_bridge_dev?(bridge, dev, vlan=nil) @@ -81,11 +79,11 @@ class OpenNebulaHM < OpenNebulaNetwork def attach_brigde_dev(bridge, dev, vlan=nil) dev = "#{dev}.#{vlan}" if vlan - system("#{COMMANDS[:brctl]} addif #{bridge} #{dev}") + OpenNebula.exec_and_log("#{COMMANDS[:brctl]} addif #{bridge} #{dev}") end def ifup(dev, vlan=nil) dev = "#{dev}.#{vlan}" if vlan - system("#{COMMANDS[:ip]} link set #{dev} up") + OpenNebula.exec_and_log("#{COMMANDS[:ip]} link set #{dev} up") end end diff --git a/src/vnm_mad/remotes/802.1Q/clean b/src/vnm_mad/remotes/802.1Q/clean new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/802.1Q/clean @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/remotes/802.1Q/post b/src/vnm_mad/remotes/802.1Q/post new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/802.1Q/post @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/remotes/802.1Q/pre b/src/vnm_mad/remotes/802.1Q/pre new file mode 100755 index 0000000000..c7ce885d28 --- /dev/null +++ b/src/vnm_mad/remotes/802.1Q/pre @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +$: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") + +require 'HostManaged' + +hm = OpenNebulaHM.from_base64(ARGV[0]) +exit hm.activate diff --git a/src/vnm_mad/Firewall.rb b/src/vnm_mad/remotes/Firewall.rb similarity index 99% rename from src/vnm_mad/Firewall.rb rename to src/vnm_mad/remotes/Firewall.rb index 586481ef05..2cc4f98eca 100644 --- a/src/vnm_mad/Firewall.rb +++ b/src/vnm_mad/remotes/Firewall.rb @@ -104,7 +104,7 @@ class OpenNebulaFirewall < OpenNebulaNetwork def run_rules(rules) rules.flatten.each do |rule| - system(rule) + OpenNebula.exec_and_log(rule) end end diff --git a/src/vnm_mad/OpenNebulaNetwork.rb b/src/vnm_mad/remotes/OpenNebulaNetwork.rb similarity index 85% rename from src/vnm_mad/OpenNebulaNetwork.rb rename to src/vnm_mad/remotes/OpenNebulaNetwork.rb index c837e88214..a944adeb8d 100644 --- a/src/vnm_mad/OpenNebulaNetwork.rb +++ b/src/vnm_mad/remotes/OpenNebulaNetwork.rb @@ -17,9 +17,14 @@ #--------------------------------------------------------------------------- # $: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), '..') require 'rexml/document' require 'OpenNebulaNic' +require 'base64' + +require 'scripts_common' +include OpenNebula CONF = { :start_vlan => 2 @@ -28,7 +33,7 @@ CONF = { COMMANDS = { :ebtables => "sudo /sbin/ebtables", :iptables => "sudo /sbin/iptables", - :brctl => "sudo /usr/sbin/brctl", + :brctl => "sudo /sbin/brctl", :ip => "sudo /sbin/ip", :vconfig => "sudo /sbin/vconfig", :virsh => "virsh -c qemu:///system", @@ -37,11 +42,8 @@ COMMANDS = { :lsmod => "/sbin/lsmod" } -# -# -# class VM - attr_accessor :nics, :filtered_nics, :vm_info + attr_accessor :nics, :vm_info def initialize(vm_root, hypervisor) @vm_root = vm_root @@ -50,7 +52,7 @@ class VM nics = Nics.new(@hypervisor) - @vm_root.elements.each("TEMPLATE/NIC") do |nic_element| + @vm_root.elements.each("TEMPLATE/NIC[VLAN='YES']") do |nic_element| nic = nics.new_nic nic_element.elements.each('*') do |nic_attribute| @@ -64,21 +66,12 @@ class VM nics << nic end - @nics = nics - @filtered_nics = nics - end - - def filter(*filter) - @filtered_nics = @nics.get(*filter) - end - - def unfilter - @filtered_nics = @nics + @nics = nics end def each_nic(block) - if @filtered_nics != nil - @filtered_nics.each do |the_nic| + if @nics != nil + @nics.each do |the_nic| block.call(the_nic) end end @@ -98,9 +91,14 @@ end class OpenNebulaNetwork attr_reader :hypervisor, :vm + def self.from_base64(vm_64, hypervisor=nil) + vm_xml = Base64::decode64(vm_64) + self.new(vm_xml, hypervisor) + end + def initialize(vm_tpl, hypervisor=nil) if !hypervisor - @hypervisor = detect_hypervisor + @hypervisor = detect_hypervisor else @hypervisor = hypervisor end @@ -108,16 +106,6 @@ class OpenNebulaNetwork @vm = VM.new(REXML::Document.new(vm_tpl).root, @hypervisor) end - def filter(*filter) - @vm.filter(*filter) - self - end - - def unfilter - @vm.unfilter - self - end - def process(&block) @vm.each_nic(block) end diff --git a/src/vnm_mad/OpenNebulaNic.rb b/src/vnm_mad/remotes/OpenNebulaNic.rb similarity index 72% rename from src/vnm_mad/OpenNebulaNic.rb rename to src/vnm_mad/remotes/OpenNebulaNic.rb index d2916a91bd..84214bd154 100644 --- a/src/vnm_mad/OpenNebulaNic.rb +++ b/src/vnm_mad/remotes/OpenNebulaNic.rb @@ -28,59 +28,11 @@ class Nics < Array def new_nic @nicClass.new end - - # finds nics that match 'args' - # 'args' can be a Hash, or an array - # args example: - # {:mac => "02:00:C0:A8:01:01", :bridge => "br0"} - # :mac, "02:00:C0:A8:01:01" - # key values may also be an array: - # {:mac => "02:00:C0:A8:01:01", :bridge => ["br0","br1"]} - def get(*args) - if args.length == 2 - dict = Hash.new - dict[args[0]] = args[1] - elsif args.length == 1 - dict = args[0] - else - return nil - end - - matching = Array.new - self.each do |e| - e_filter = Hash.new - dict.each_key{|k| e_filter[k] = e[k]} - if compare(e_filter,dict) - matching << e - end - end - - if matching.empty? - nil - else - matching - end - end - - def compare(hash1, hash2) - #hash1 has a single value per key - #hash2 may contain an array of values - hash1.each do |k,v| - return false if !hash2[k] - v2 = hash2[k] - if hash2[k].kind_of?(Array) - return false if !v2.include? v - else - return false if v != v2 - end - end - true - end end -# A NIC using KVM. This class implements functions to get the physical interface -# that the NIC is using +# A NIC using KVM. This class implements functions to get the physical interface +# that the NIC is using class NicKVM < Hash def initialize super(nil) @@ -118,8 +70,8 @@ class NicKVM < Hash end -# A NIC using Xen. This class implements functions to get the physical interface -# that the NIC is using +# A NIC using Xen. This class implements functions to get the physical interface +# that the NIC is using class NicXen < Hash def initialize super(nil) diff --git a/src/vnm_mad/remotes/dummy/clean b/src/vnm_mad/remotes/dummy/clean new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/dummy/clean @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/remotes/dummy/post b/src/vnm_mad/remotes/dummy/post new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/dummy/post @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/remotes/dummy/pre b/src/vnm_mad/remotes/dummy/pre new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/dummy/pre @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/Ebtables.rb b/src/vnm_mad/remotes/ebtables/Ebtables.rb similarity index 91% rename from src/vnm_mad/Ebtables.rb rename to src/vnm_mad/remotes/ebtables/Ebtables.rb index 71f9bb1e8e..c22ad69340 100644 --- a/src/vnm_mad/Ebtables.rb +++ b/src/vnm_mad/remotes/ebtables/Ebtables.rb @@ -14,15 +14,19 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'OpenNebulaNetwork' + class EbtablesVLAN < OpenNebulaNetwork def initialize(vm, hypervisor = nil) super(vm,hypervisor) end def ebtables(rule) - system("#{COMMANDS[:ebtables]} -A #{rule}") + OpenNebula.exec_and_log("#{COMMANDS[:ebtables]} -A #{rule}") end + # Activates ebtables rules + # def activate process do |nic| tap = nic[:tap] @@ -42,6 +46,8 @@ class EbtablesVLAN < OpenNebulaNetwork ebtables(out_rule) end end + + return 0 end def deactivate @@ -59,6 +65,8 @@ class EbtablesVLAN < OpenNebulaNetwork end remove_rules(tap) end + + return 0 end def rules @@ -74,6 +82,6 @@ class EbtablesVLAN < OpenNebulaNetwork end def remove_rule(rule) - system("#{COMMANDS[:ebtables]} -D FORWARD #{rule}") + OpenNebula.exec_and_log("#{COMMANDS[:ebtables]} -D FORWARD #{rule}") end end diff --git a/src/vnm_mad/firewall b/src/vnm_mad/remotes/ebtables/clean similarity index 83% rename from src/vnm_mad/firewall rename to src/vnm_mad/remotes/ebtables/clean index ca5507d7f9..0aaefc7e02 100755 --- a/src/vnm_mad/firewall +++ b/src/vnm_mad/remotes/ebtables/clean @@ -17,21 +17,12 @@ #--------------------------------------------------------------------------- # $: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") -require 'base64' -require 'OpenNebulaNetwork' -require 'Firewall' +require 'Ebtables' -action = ARGV[0] -template = ARGV[1] +template = ARGV[0] -vm_xml = Base64::decode64(template) +onevlan = EbtablesVLAN.from_base64(template) -fw = OpenNebulaFirewall.new(vm_xml) - -case action -when "on" - fw.activate -when "off" - fw.deactivate -end +exit onevlan.deactivate diff --git a/src/vnm_mad/ebtables-vlan b/src/vnm_mad/remotes/ebtables/post similarity index 75% rename from src/vnm_mad/ebtables-vlan rename to src/vnm_mad/remotes/ebtables/post index d4e72abe34..c142e41a2f 100755 --- a/src/vnm_mad/ebtables-vlan +++ b/src/vnm_mad/remotes/ebtables/post @@ -17,24 +17,9 @@ #--------------------------------------------------------------------------- # $: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") -require 'base64' -require 'OpenNebulaNetwork' require 'Ebtables' -action = ARGV[0] -template = ARGV[1] - -# Uncomment to act only on the listed bridges. -#FILTERED_BRIDGES = ['br0'] - -vm_xml = Base64::decode64(template) -onevlan = EbtablesVLAN.new(vm_xml) - -case action -when "on" - onevlan.filter(:bridge => FILTERED_BRIDGES) if defined? FILTERED_BRIDGES - onevlan.activate -when "off" - onevlan.deactivate -end +onevlan = EbtablesVLAN.from_base64(ARGV[0]) +exit onevlan.activate diff --git a/src/vnm_mad/remotes/ebtables/pre b/src/vnm_mad/remotes/ebtables/pre new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/ebtables/pre @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/hm-vlan b/src/vnm_mad/remotes/fw/clean similarity index 89% rename from src/vnm_mad/hm-vlan rename to src/vnm_mad/remotes/fw/clean index 63f1dc53e1..95c11359c4 100755 --- a/src/vnm_mad/hm-vlan +++ b/src/vnm_mad/remotes/fw/clean @@ -17,13 +17,11 @@ #--------------------------------------------------------------------------- # $: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") -require 'base64' require 'OpenNebulaNetwork' -require 'HostManaged' +require 'Firewall' -template = ARGV[0] -vm_xml = Base64::decode64(template) +fw = OpenNebulaFirewall.from_base64(ARGV[0]) -hm = OpenNebulaHM.new(vm_xml) -hm.activate +fw.deactivate diff --git a/src/vnm_mad/openvswitch-vlan b/src/vnm_mad/remotes/fw/post similarity index 89% rename from src/vnm_mad/openvswitch-vlan rename to src/vnm_mad/remotes/fw/post index 1cd64fcf1b..6458772e86 100755 --- a/src/vnm_mad/openvswitch-vlan +++ b/src/vnm_mad/remotes/fw/post @@ -17,13 +17,11 @@ #--------------------------------------------------------------------------- # $: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") -require 'base64' require 'OpenNebulaNetwork' -require 'OpenvSwitch' +require 'Firewall' -template = ARGV[0] -vm_xml = Base64::decode64(template) +fw = OpenNebulaFirewall.from_base64(ARGV[0]) -onevlan = OpenvSwitchVLAN.new(vm_xml) -onevlan.activate +fw.activate diff --git a/src/vnm_mad/remotes/fw/pre b/src/vnm_mad/remotes/fw/pre new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/fw/pre @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/OpenvSwitch.rb b/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb similarity index 94% rename from src/vnm_mad/OpenvSwitch.rb rename to src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb index 2ba84ca1ea..9716d99f8a 100644 --- a/src/vnm_mad/OpenvSwitch.rb +++ b/src/vnm_mad/remotes/ovswitch/OpenvSwitch.rb @@ -14,6 +14,8 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'OpenNebulaNetwork' + class OpenvSwitchVLAN < OpenNebulaNetwork def initialize(vm, hypervisor = nil) super(vm,hypervisor) @@ -30,7 +32,9 @@ class OpenvSwitchVLAN < OpenNebulaNetwork cmd = "#{COMMANDS[:ovs_vsctl]} set Port #{nic[:tap]} " cmd << "tag=#{vlan}" - system(cmd) + OpenNebula.exec_and_log(cmd) end + + return 0 end end diff --git a/src/vnm_mad/remotes/ovswitch/clean b/src/vnm_mad/remotes/ovswitch/clean new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/ovswitch/clean @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/remotes/ovswitch/post b/src/vnm_mad/remotes/ovswitch/post new file mode 100755 index 0000000000..e59bd2ead6 --- /dev/null +++ b/src/vnm_mad/remotes/ovswitch/post @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +$: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") + +require 'OpenvSwitch' + +onevlan = OpenvSwitchVLAN.from_base64(ARGV[0]) +exit onevlan.activate() diff --git a/src/vnm_mad/remotes/ovswitch/pre b/src/vnm_mad/remotes/ovswitch/pre new file mode 100755 index 0000000000..44337c50d2 --- /dev/null +++ b/src/vnm_mad/remotes/ovswitch/pre @@ -0,0 +1,19 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +exit 0 \ No newline at end of file diff --git a/src/vnm_mad/test/OpenNebulaNetwork_spec.rb b/src/vnm_mad/remotes/test/OpenNebulaNetwork_spec.rb similarity index 67% rename from src/vnm_mad/test/OpenNebulaNetwork_spec.rb rename to src/vnm_mad/remotes/test/OpenNebulaNetwork_spec.rb index c8e7c14ccd..c06453ffb0 100644 --- a/src/vnm_mad/test/OpenNebulaNetwork_spec.rb +++ b/src/vnm_mad/remotes/test/OpenNebulaNetwork_spec.rb @@ -1,18 +1,24 @@ #!/usr/bin/env ruby -$: << File.dirname(__FILE__) + '/..' \ - << './' +$: << File.dirname(__FILE__) + '/..' +$: << File.dirname(__FILE__) + '/../ebtables' +$: << File.dirname(__FILE__) + '/../802.1Q' +$: << File.dirname(__FILE__) + '/../ovswitch' +$: << File.dirname(__FILE__) + '/../../../mad/ruby' +$: << './' +$: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), '..') +$: << File.join(File.dirname(__FILE__),'../../../mad/ruby/') require 'rubygems' require 'rspec' -require 'SystemMock' require 'pp' require 'OpenNebulaNetwork' -require 'Ebtables' +require 'ebtables/Ebtables' require 'Firewall' -require 'HostManaged' -require 'OpenvSwitch' +require '802.1Q/HostManaged' +require 'ovswitch/OpenvSwitch' OUTPUT = Hash.new Dir[File.dirname(__FILE__) + "/output/**"].each do |f| @@ -20,6 +26,9 @@ Dir[File.dirname(__FILE__) + "/output/**"].each do |f| OUTPUT[key] = File.read(f) end +require 'scripts_common' +require 'SystemMock' +include OpenNebula include SystemMock RSpec.configure do |config| @@ -36,40 +45,28 @@ describe 'networking' do } onevlan = OpenNebulaNetwork.new(OUTPUT[:onevm_show],"kvm") nics_expected = [{:bridge=>"br0", - :ip=>"172.16.0.100", - :mac=>"02:00:ac:10:00:64", - :network=>"Small network", - :network_id=>"0", - :tap=>"vnet0"}, - {:bridge=>"br1", - :ip=>"10.1.1.1", - :mac=>"02:00:0a:01:01:01", - :network=>"r1", - :network_id=>"1", - :tap=>"vnet1"}, - {:bridge=>"br2", - :ip=>"10.1.2.1", - :mac=>"02:00:0a:01:02:01", - :network=>"r2", - :network_id=>"2", - :tap=>"vnet2"}] - onevlan.vm.nics.should == nics_expected - end - - it "filter nics in kvm" do - $capture_commands = { - /virsh.*dumpxml/ => OUTPUT[:virsh_dumpxml] - } - onevlan = OpenNebulaNetwork.new(OUTPUT[:onevm_show],"kvm") - onevlan.filter(:bridge => "br1") - nics_expected = [{:bridge=>"br1", + :ip=>"172.16.0.100", + :mac=>"02:00:ac:10:00:64", + :network=>"Small network", + :network_id=>"0", + :vlan=>"YES", + :tap=>"vnet0"}, + {:bridge=>"br1", :ip=>"10.1.1.1", :mac=>"02:00:0a:01:01:01", :network=>"r1", :network_id=>"1", - :tap=>"vnet1"}] - - onevlan.vm.filtered_nics.should == nics_expected + :vlan=>"YES", + :tap=>"vnet1"}, + {:bridge=>"br2", + :ip=>"10.1.2.1", + :mac=>"02:00:0a:01:02:01", + :network=>"r2", + :network_id=>"2", + :vlan=>"YES", + :tap=>"vnet2"}] + + onevlan.vm.nics.should == nics_expected end end @@ -88,7 +85,10 @@ describe 'ebtables' do "sudo /sbin/ebtables -A FORWARD -s ! 02:00:0a:01:01:01 -i vnet1 -j DROP", "sudo /sbin/ebtables -A FORWARD -s ! 02:00:0a:01:02:00/ff:ff:ff:ff:ff:00 -o vnet2 -j DROP", "sudo /sbin/ebtables -A FORWARD -s ! 02:00:0a:01:02:01 -i vnet2 -j DROP"] - $collector[:system].should == ebtables_cmds + + ebtables_cmds.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end end @@ -106,7 +106,9 @@ describe 'openvswitch' do "sudo /usr/local/bin/ovs-vsctl set Port vnet2 tag=4" ] - $collector[:system].should == openvswitch_tags + openvswitch_tags.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end it "force VLAN_ID for Open vSwitch vlans in kvm" do @@ -117,12 +119,14 @@ describe 'openvswitch' do } onevlan = OpenvSwitchVLAN.new(OUTPUT[:onevm_show_vlan_id_kvm],"kvm") onevlan.activate - + onevlan_rules = ["sudo /usr/local/bin/ovs-vsctl set Port vnet0 tag=6", "sudo /usr/local/bin/ovs-vsctl set Port vnet1 tag=50", "sudo /usr/local/bin/ovs-vsctl set Port vnet1 tag=51"] - $collector[:system].should == onevlan_rules + onevlan_rules.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end end @@ -146,7 +150,9 @@ describe 'firewall' do "sudo /sbin/iptables -A one-36-3 -p icmp -m state --state ESTABLISHED -j ACCEPT", "sudo /sbin/iptables -A one-36-3 -p icmp -j DROP"] - $collector[:system].should == fw_activate_rules + fw_activate_rules.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end end @@ -155,20 +161,23 @@ describe 'host-managed' do $capture_commands = { /virsh.*dumpxml/ => OUTPUT[:virsh_dumpxml_phydev], /brctl show/ => OUTPUT[:brctl_show], - /brctl add/ => nil, - /vconfig/ => nil, - /ip link/ => nil + /brctl add/ => nil, + /vconfig/ => nil, + /ip link/ => nil } hm = OpenNebulaHM.new(OUTPUT[:onevm_show_phydev_kvm],"kvm") hm.activate - hm_activate_rules = ["sudo /usr/sbin/brctl addbr onebr6", + hm_activate_rules = ["sudo /sbin/brctl addbr onebr6", "sudo /sbin/ip link set onebr6 up", "sudo /sbin/ip link show eth0.8", "sudo /sbin/vconfig add eth0 8", "sudo /sbin/ip link set eth0.8 up", - "sudo /usr/sbin/brctl addif onebr6 eth0.8"] - $collector[:system].should == hm_activate_rules + "sudo /sbin/brctl addif onebr6 eth0.8"] + + hm_activate_rules.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end it "force VLAN_ID for vlans in kvm" do @@ -182,19 +191,21 @@ describe 'host-managed' do hm = OpenNebulaHM.new(OUTPUT[:onevm_show_vlan_id_kvm],"kvm") hm.activate - hm_vlan_id = ["sudo /usr/sbin/brctl addbr onebr10", + hm_vlan_id = ["sudo /sbin/brctl addbr onebr10", "sudo /sbin/ip link set onebr10 up", "sudo /sbin/ip link show eth0.50", "sudo /sbin/vconfig add eth0 50", "sudo /sbin/ip link set eth0.50 up", - "sudo /usr/sbin/brctl addif onebr10 eth0.50", - "sudo /usr/sbin/brctl addbr specialbr", + "sudo /sbin/brctl addif onebr10 eth0.50", + "sudo /sbin/brctl addbr specialbr", "sudo /sbin/ip link set specialbr up", "sudo /sbin/ip link show eth0.51", "sudo /sbin/vconfig add eth0 51", "sudo /sbin/ip link set eth0.51 up", - "sudo /usr/sbin/brctl addif specialbr eth0.51"] + "sudo /sbin/brctl addif specialbr eth0.51"] - $collector[:system].should == hm_vlan_id + hm_vlan_id.map{|c| c + " 2>&1 1>/dev/null"}.each do |cmd| + $collector[:backtick].include?(cmd).should == true + end end end diff --git a/src/vnm_mad/test/SystemMock.rb b/src/vnm_mad/remotes/test/SystemMock.rb similarity index 88% rename from src/vnm_mad/test/SystemMock.rb rename to src/vnm_mad/remotes/test/SystemMock.rb index 9c2d122d47..6e83e85411 100644 --- a/src/vnm_mad/test/SystemMock.rb +++ b/src/vnm_mad/remotes/test/SystemMock.rb @@ -1,14 +1,15 @@ module SystemMock - require 'open3' + def execute_cmd(cmd) if $capture_commands $capture_commands.each do |regex, output| if cmd.match(regex) + Kernel.send(:`,":;exit 0") return output end end end - Open3.popen3(cmd){|stdin, stdout, stderr| stdout.read} + Kernel.send(:`,cmd) end def `(cmd) diff --git a/src/vnm_mad/test/output/brctl_show b/src/vnm_mad/remotes/test/output/brctl_show similarity index 100% rename from src/vnm_mad/test/output/brctl_show rename to src/vnm_mad/remotes/test/output/brctl_show diff --git a/src/vnm_mad/test/output/kvm_lsmod b/src/vnm_mad/remotes/test/output/kvm_lsmod similarity index 100% rename from src/vnm_mad/test/output/kvm_lsmod rename to src/vnm_mad/remotes/test/output/kvm_lsmod diff --git a/src/vnm_mad/test/output/kvm_uname_a b/src/vnm_mad/remotes/test/output/kvm_uname_a similarity index 100% rename from src/vnm_mad/test/output/kvm_uname_a rename to src/vnm_mad/remotes/test/output/kvm_uname_a diff --git a/src/vnm_mad/test/output/onevm_show b/src/vnm_mad/remotes/test/output/onevm_show similarity index 95% rename from src/vnm_mad/test/output/onevm_show rename to src/vnm_mad/remotes/test/output/onevm_show index ec56cbf225..28b962f202 100644 --- a/src/vnm_mad/test/output/onevm_show +++ b/src/vnm_mad/remotes/test/output/onevm_show @@ -37,6 +37,7 @@ + @@ -44,6 +45,7 @@ + @@ -51,6 +53,7 @@ + diff --git a/src/vnm_mad/test/output/onevm_show_phydev_kvm b/src/vnm_mad/remotes/test/output/onevm_show_phydev_kvm similarity index 96% rename from src/vnm_mad/test/output/onevm_show_phydev_kvm rename to src/vnm_mad/remotes/test/output/onevm_show_phydev_kvm index 610bcb9d74..5a7541662f 100644 --- a/src/vnm_mad/test/output/onevm_show_phydev_kvm +++ b/src/vnm_mad/remotes/test/output/onevm_show_phydev_kvm @@ -37,6 +37,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/src/vnm_mad/test/output/onevm_show_vlan_id_kvm b/src/vnm_mad/remotes/test/output/onevm_show_vlan_id_kvm similarity index 95% rename from src/vnm_mad/test/output/onevm_show_vlan_id_kvm rename to src/vnm_mad/remotes/test/output/onevm_show_vlan_id_kvm index e70880289d..637838f3b5 100644 --- a/src/vnm_mad/test/output/onevm_show_vlan_id_kvm +++ b/src/vnm_mad/remotes/test/output/onevm_show_vlan_id_kvm @@ -37,6 +37,7 @@ + @@ -45,6 +46,7 @@ + @@ -54,6 +56,7 @@ + diff --git a/src/vnm_mad/test/output/onevm_show_xen b/src/vnm_mad/remotes/test/output/onevm_show_xen similarity index 96% rename from src/vnm_mad/test/output/onevm_show_xen rename to src/vnm_mad/remotes/test/output/onevm_show_xen index bff85d160a..9f0685ad44 100644 --- a/src/vnm_mad/test/output/onevm_show_xen +++ b/src/vnm_mad/remotes/test/output/onevm_show_xen @@ -33,6 +33,7 @@ + @@ -42,6 +43,7 @@ + diff --git a/src/vnm_mad/test/output/virsh_dumpxml b/src/vnm_mad/remotes/test/output/virsh_dumpxml similarity index 100% rename from src/vnm_mad/test/output/virsh_dumpxml rename to src/vnm_mad/remotes/test/output/virsh_dumpxml diff --git a/src/vnm_mad/test/output/virsh_dumpxml_phydev b/src/vnm_mad/remotes/test/output/virsh_dumpxml_phydev similarity index 100% rename from src/vnm_mad/test/output/virsh_dumpxml_phydev rename to src/vnm_mad/remotes/test/output/virsh_dumpxml_phydev diff --git a/src/vnm_mad/test/output/virsh_dumpxml_vlan_id b/src/vnm_mad/remotes/test/output/virsh_dumpxml_vlan_id similarity index 100% rename from src/vnm_mad/test/output/virsh_dumpxml_vlan_id rename to src/vnm_mad/remotes/test/output/virsh_dumpxml_vlan_id diff --git a/src/vnm_mad/test/output/xen_lsmod b/src/vnm_mad/remotes/test/output/xen_lsmod similarity index 100% rename from src/vnm_mad/test/output/xen_lsmod rename to src/vnm_mad/remotes/test/output/xen_lsmod diff --git a/src/vnm_mad/test/output/xen_uname_a b/src/vnm_mad/remotes/test/output/xen_uname_a similarity index 100% rename from src/vnm_mad/test/output/xen_uname_a rename to src/vnm_mad/remotes/test/output/xen_uname_a diff --git a/src/vnm_mad/test/output/xm_domid b/src/vnm_mad/remotes/test/output/xm_domid similarity index 100% rename from src/vnm_mad/test/output/xm_domid rename to src/vnm_mad/remotes/test/output/xm_domid diff --git a/src/vnm_mad/test/output/xm_network_list b/src/vnm_mad/remotes/test/output/xm_network_list similarity index 100% rename from src/vnm_mad/test/output/xm_network_list rename to src/vnm_mad/remotes/test/output/xm_network_list diff --git a/src/xml/expr_arith.cc b/src/xml/expr_arith.cc index b8c9394fbf..a27aa8c15b 100644 --- a/src/xml/expr_arith.cc +++ b/src/xml/expr_arith.cc @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.3" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -74,7 +73,7 @@ /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 17 "expr_arith.y" #include @@ -130,8 +129,8 @@ extern "C" -/* Line 189 of yacc.c */ -#line 135 "expr_arith.cc" +/* Line 268 of yacc.c */ +#line 134 "expr_arith.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -170,7 +169,7 @@ extern "C" typedef union YYSTYPE { -/* Line 214 of yacc.c */ +/* Line 293 of yacc.c */ #line 78 "expr_arith.y" char * val_str; @@ -179,8 +178,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 184 "expr_arith.cc" +/* Line 293 of yacc.c */ +#line 183 "expr_arith.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -204,8 +203,8 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 209 "expr_arith.cc" +/* Line 343 of yacc.c */ +#line 208 "expr_arith.cc" #ifdef short # undef short @@ -308,11 +307,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -335,24 +334,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -383,23 +382,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -419,6 +402,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 10 /* YYLAST -- Last index in YYTABLE. */ @@ -532,8 +535,8 @@ static const yytype_uint8 yyr2[] = 3, 2, 3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -564,8 +567,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -574,6 +576,12 @@ static const yytype_uint8 yytable[] = 4, 5, 11, 12, 13, 14 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-5)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_int8 yycheck[] = { 1, 5, 6, -1, 5, 0, 3, 4, 5, 6, @@ -622,7 +630,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -890,7 +897,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -993,115 +999,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1144,6 +1177,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, mc, oxml, result, error_msg) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1160,12 +1194,9 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1381,7 +1412,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1412,8 +1443,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1469,21 +1500,21 @@ yyreduce: { case 2: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 100 "expr_arith.y" - { result = static_cast((yyvsp[(1) - (1)].val_float));;} + { result = static_cast((yyvsp[(1) - (1)].val_float));} break; case 3: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 101 "expr_arith.y" - { result = 0; ;} + { result = 0; } break; case 4: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 104 "expr_arith.y" { float val = 0.0; @@ -1509,71 +1540,82 @@ yyreduce: } (yyval.val_float) = val; - ;} + } break; case 5: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 129 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(1) - (1)].val_float); ;} + { (yyval.val_float) = (yyvsp[(1) - (1)].val_float); } break; case 6: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 130 "expr_arith.y" - { (yyval.val_float) = static_cast((yyvsp[(1) - (1)].val_int)); ;} + { (yyval.val_float) = static_cast((yyvsp[(1) - (1)].val_int)); } break; case 7: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 131 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) + (yyvsp[(3) - (3)].val_float);;} + { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) + (yyvsp[(3) - (3)].val_float);} break; case 8: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 132 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) - (yyvsp[(3) - (3)].val_float);;} + { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) - (yyvsp[(3) - (3)].val_float);} break; case 9: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 133 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) * (yyvsp[(3) - (3)].val_float);;} + { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) * (yyvsp[(3) - (3)].val_float);} break; case 10: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 134 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) / (yyvsp[(3) - (3)].val_float);;} + { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) / (yyvsp[(3) - (3)].val_float);} break; case 11: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 135 "expr_arith.y" - { (yyval.val_float) = - (yyvsp[(2) - (2)].val_float);;} + { (yyval.val_float) = - (yyvsp[(2) - (2)].val_float);} break; case 12: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 136 "expr_arith.y" - { (yyval.val_float) = (yyvsp[(2) - (3)].val_float);;} + { (yyval.val_float) = (yyvsp[(2) - (3)].val_float);} break; -/* Line 1464 of yacc.c */ -#line 1575 "expr_arith.cc" +/* Line 1806 of yacc.c */ +#line 1606 "expr_arith.cc" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1602,6 +1644,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1609,37 +1655,36 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (&yylloc, mc, oxml, result, error_msg, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, mc, oxml, result, error_msg, yymsg); - } - else - { - yyerror (&yylloc, mc, oxml, result, error_msg, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, mc, oxml, result, error_msg, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1699,7 +1744,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1763,8 +1808,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, mc, oxml, result, error_msg); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, mc, oxml, result, error_msg); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1789,7 +1839,7 @@ yyreturn: -/* Line 1684 of yacc.c */ +/* Line 2067 of yacc.c */ #line 139 "expr_arith.y" diff --git a/src/xml/expr_arith.h b/src/xml/expr_arith.h index 66cd7ebbb4..8dec688916 100644 --- a/src/xml/expr_arith.h +++ b/src/xml/expr_arith.h @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,7 +49,7 @@ typedef union YYSTYPE { -/* Line 1685 of yacc.c */ +/* Line 2068 of yacc.c */ #line 78 "expr_arith.y" char * val_str; @@ -59,8 +58,8 @@ typedef union YYSTYPE -/* Line 1685 of yacc.c */ -#line 64 "expr_arith.hh" +/* Line 2068 of yacc.c */ +#line 63 "expr_arith.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/xml/expr_bool.cc b/src/xml/expr_bool.cc index 0d9c80598f..be3802607f 100644 --- a/src/xml/expr_bool.cc +++ b/src/xml/expr_bool.cc @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.3" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -74,7 +73,7 @@ /* Copy the first part of user declarations. */ -/* Line 189 of yacc.c */ +/* Line 268 of yacc.c */ #line 17 "expr_bool.y" #include @@ -135,8 +134,8 @@ void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val); -/* Line 189 of yacc.c */ -#line 140 "expr_bool.cc" +/* Line 268 of yacc.c */ +#line 139 "expr_bool.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -175,7 +174,7 @@ void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val); typedef union YYSTYPE { -/* Line 214 of yacc.c */ +/* Line 293 of yacc.c */ #line 83 "expr_bool.y" char * val_str; @@ -184,8 +183,8 @@ typedef union YYSTYPE -/* Line 214 of yacc.c */ -#line 189 "expr_bool.cc" +/* Line 293 of yacc.c */ +#line 188 "expr_bool.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -209,8 +208,8 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -/* Line 264 of yacc.c */ -#line 214 "expr_bool.cc" +/* Line 343 of yacc.c */ +#line 213 "expr_bool.cc" #ifdef short # undef short @@ -313,11 +312,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -340,24 +339,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -388,23 +387,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -424,6 +407,26 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 12 /* YYLAST -- Last index in YYTABLE. */ @@ -540,8 +543,8 @@ static const yytype_uint8 yyr2[] = 3, 3, 3, 4, 3, 3, 2, 3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { @@ -574,8 +577,7 @@ static const yytype_int8 yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ + number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { @@ -584,6 +586,12 @@ static const yytype_uint8 yytable[] = 16, 17, 18, 26, 27, 28, 19, 21, 20, 22 }; +#define yypact_value_is_default(yystate) \ + ((yystate) == (-6)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + static const yytype_int8 yycheck[] = { 1, 3, 3, 0, 9, 7, 4, 5, 4, 5, @@ -633,7 +641,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -901,7 +908,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1004,115 +1010,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - int yyn = yypact[yystate]; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1155,6 +1188,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, mc, oxml, result, error_msg) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1171,12 +1205,9 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1392,7 +1423,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1423,8 +1454,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1480,152 +1511,163 @@ yyreduce: { case 2: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 103 "expr_bool.y" - { result=(yyvsp[(1) - (1)].val_int); ;} + { result=(yyvsp[(1) - (1)].val_int); } break; case 3: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 104 "expr_bool.y" - { result=true; ;} + { result=true; } break; case 4: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 107 "expr_bool.y" { int val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val == (yyvsp[(3) - (3)].val_int);;} + (yyval.val_int) = val == (yyvsp[(3) - (3)].val_int);} break; case 5: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 112 "expr_bool.y" { int val; get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); - (yyval.val_int) = val != (yyvsp[(4) - (4)].val_int);;} + (yyval.val_int) = val != (yyvsp[(4) - (4)].val_int);} break; case 6: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 117 "expr_bool.y" { int val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val > (yyvsp[(3) - (3)].val_int);;} + (yyval.val_int) = val > (yyvsp[(3) - (3)].val_int);} break; case 7: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 122 "expr_bool.y" { int val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val < (yyvsp[(3) - (3)].val_int);;} + (yyval.val_int) = val < (yyvsp[(3) - (3)].val_int);} break; case 8: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 127 "expr_bool.y" { float val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val == (yyvsp[(3) - (3)].val_float);;} + (yyval.val_int) = val == (yyvsp[(3) - (3)].val_float);} break; case 9: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 132 "expr_bool.y" { float val; get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); - (yyval.val_int) = val != (yyvsp[(4) - (4)].val_float);;} + (yyval.val_int) = val != (yyvsp[(4) - (4)].val_float);} break; case 10: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 137 "expr_bool.y" { float val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val > (yyvsp[(3) - (3)].val_float);;} + (yyval.val_int) = val > (yyvsp[(3) - (3)].val_float);} break; case 11: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 142 "expr_bool.y" { float val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val < (yyvsp[(3) - (3)].val_float);;} + (yyval.val_int) = val < (yyvsp[(3) - (3)].val_float);} break; case 12: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 147 "expr_bool.y" { string val; get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = (val.empty() || (yyvsp[(3) - (3)].val_str)==0) ? false : fnmatch((yyvsp[(3) - (3)].val_str),val.c_str(),0)==0;;} + (yyval.val_int) = (val.empty() || (yyvsp[(3) - (3)].val_str)==0) ? false : fnmatch((yyvsp[(3) - (3)].val_str),val.c_str(),0)==0;} break; case 13: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 152 "expr_bool.y" { string val; get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); - (yyval.val_int) = (val.empty() || (yyvsp[(4) - (4)].val_str)==0) ? false : fnmatch((yyvsp[(4) - (4)].val_str),val.c_str(),0)!=0;;} + (yyval.val_int) = (val.empty() || (yyvsp[(4) - (4)].val_str)==0) ? false : fnmatch((yyvsp[(4) - (4)].val_str),val.c_str(),0)!=0;} break; case 14: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 157 "expr_bool.y" - { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) && (yyvsp[(3) - (3)].val_int); ;} + { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) && (yyvsp[(3) - (3)].val_int); } break; case 15: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 158 "expr_bool.y" - { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) || (yyvsp[(3) - (3)].val_int); ;} + { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) || (yyvsp[(3) - (3)].val_int); } break; case 16: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 159 "expr_bool.y" - { (yyval.val_int) = ! (yyvsp[(2) - (2)].val_int); ;} + { (yyval.val_int) = ! (yyvsp[(2) - (2)].val_int); } break; case 17: -/* Line 1464 of yacc.c */ +/* Line 1806 of yacc.c */ #line 160 "expr_bool.y" - { (yyval.val_int) = (yyvsp[(2) - (3)].val_int); ;} + { (yyval.val_int) = (yyvsp[(2) - (3)].val_int); } break; -/* Line 1464 of yacc.c */ -#line 1627 "expr_bool.cc" +/* Line 1806 of yacc.c */ +#line 1658 "expr_bool.cc" default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1654,6 +1696,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -1661,37 +1707,36 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (&yylloc, mc, oxml, result, error_msg, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, mc, oxml, result, error_msg, yymsg); - } - else - { - yyerror (&yylloc, mc, oxml, result, error_msg, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, mc, oxml, result, error_msg, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1751,7 +1796,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1815,8 +1860,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, mc, oxml, result, error_msg); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, mc, oxml, result, error_msg); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1841,7 +1891,7 @@ yyreturn: -/* Line 1684 of yacc.c */ +/* Line 2067 of yacc.c */ #line 163 "expr_bool.y" diff --git a/src/xml/expr_bool.h b/src/xml/expr_bool.h index 3e0c95e1f6..0f561150f4 100644 --- a/src/xml/expr_bool.h +++ b/src/xml/expr_bool.h @@ -1,9 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.4.3. */ +/* A Bison parser, made by GNU Bison 2.5. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,7 +49,7 @@ typedef union YYSTYPE { -/* Line 1685 of yacc.c */ +/* Line 2068 of yacc.c */ #line 83 "expr_bool.y" char * val_str; @@ -59,8 +58,8 @@ typedef union YYSTYPE -/* Line 1685 of yacc.c */ -#line 64 "expr_bool.hh" +/* Line 2068 of yacc.c */ +#line 63 "expr_bool.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */