A few different commits merged in nova that changes slightly the HyperVDriver. Those changes should be included in compute-hyperv as well. Most significant changes: - usage of six.moves.range instead of xrange - usage of six.iteritems - VIFDriver using @abs.abstractmethod - vhdutilsv2 get_internal_vhd_size_by_file_size updated docstring - eventhandler VM State Suspended to transition map Change-Id: I850ba905b2418fb8edb4fd92a8afc7f2f1eac646
		
			
				
	
	
		
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright 2012 Pedro Navarro Perez
 | 
						|
# Copyright 2013 Cloudbase Solutions Srl
 | 
						|
# All Rights Reserved.
 | 
						|
#
 | 
						|
#    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.
 | 
						|
 | 
						|
"""
 | 
						|
Helper methods for operations related to the management of volumes
 | 
						|
and storage repositories on Windows Server 2012 and above
 | 
						|
"""
 | 
						|
import sys
 | 
						|
import time
 | 
						|
 | 
						|
if sys.platform == 'win32':
 | 
						|
    import wmi
 | 
						|
 | 
						|
from nova import utils
 | 
						|
from oslo_config import cfg
 | 
						|
from oslo_log import log as logging
 | 
						|
from six.moves import range
 | 
						|
 | 
						|
from hyperv.i18n import _
 | 
						|
from hyperv.nova import basevolumeutils
 | 
						|
from hyperv.nova import vmutils
 | 
						|
 | 
						|
LOG = logging.getLogger(__name__)
 | 
						|
CONF = cfg.CONF
 | 
						|
 | 
						|
 | 
						|
class VolumeUtilsV2(basevolumeutils.BaseVolumeUtils):
 | 
						|
    _CHAP_AUTH_TYPE = 'ONEWAYCHAP'
 | 
						|
 | 
						|
    def __init__(self, host='.'):
 | 
						|
        super(VolumeUtilsV2, self).__init__(host)
 | 
						|
 | 
						|
        storage_namespace = '//%s/root/microsoft/windows/storage' % host
 | 
						|
        if sys.platform == 'win32':
 | 
						|
            self._conn_storage = wmi.WMI(moniker=storage_namespace)
 | 
						|
 | 
						|
    def _login_target_portal(self, target_portal):
 | 
						|
        (target_address,
 | 
						|
         target_port) = utils.parse_server_string(target_portal)
 | 
						|
 | 
						|
        # Checking if the portal is already connected.
 | 
						|
        portal = self._conn_storage.query("SELECT * FROM "
 | 
						|
                                          "MSFT_iSCSITargetPortal "
 | 
						|
                                          "WHERE TargetPortalAddress='%s' "
 | 
						|
                                          "AND TargetPortalPortNumber='%s'"
 | 
						|
                                          % (target_address, target_port))
 | 
						|
        if portal:
 | 
						|
            portal[0].Update()
 | 
						|
        else:
 | 
						|
            # Adding target portal to iscsi initiator. Sending targets
 | 
						|
            portal = self._conn_storage.MSFT_iSCSITargetPortal
 | 
						|
            portal.New(TargetPortalAddress=target_address,
 | 
						|
                       TargetPortalPortNumber=target_port)
 | 
						|
 | 
						|
    def login_storage_target(self, target_lun, target_iqn, target_portal,
 | 
						|
                             auth_username=None, auth_password=None):
 | 
						|
        """Ensure that the target is logged in."""
 | 
						|
 | 
						|
        self._login_target_portal(target_portal)
 | 
						|
 | 
						|
        retry_count = CONF.hyperv.volume_attach_retry_count
 | 
						|
 | 
						|
        # If the target is not connected, at least two iterations are needed:
 | 
						|
        # one for performing the login and another one for checking if the
 | 
						|
        # target was logged in successfully.
 | 
						|
        if retry_count < 2:
 | 
						|
            retry_count = 2
 | 
						|
 | 
						|
        for attempt in range(retry_count):
 | 
						|
            target = self._conn_storage.query("SELECT * FROM MSFT_iSCSITarget "
 | 
						|
                                              "WHERE NodeAddress='%s' " %
 | 
						|
                                              target_iqn)
 | 
						|
 | 
						|
            if target and target[0].IsConnected:
 | 
						|
                if attempt == 0:
 | 
						|
                    # The target was already connected but an update may be
 | 
						|
                    # required
 | 
						|
                    target[0].Update()
 | 
						|
                return
 | 
						|
            try:
 | 
						|
                target = self._conn_storage.MSFT_iSCSITarget
 | 
						|
                auth = {}
 | 
						|
                if auth_username and auth_password:
 | 
						|
                    auth['AuthenticationType'] = self._CHAP_AUTH_TYPE
 | 
						|
                    auth['ChapUsername'] = auth_username
 | 
						|
                    auth['ChapSecret'] = auth_password
 | 
						|
                target.Connect(NodeAddress=target_iqn,
 | 
						|
                               IsPersistent=True, **auth)
 | 
						|
                time.sleep(CONF.hyperv.volume_attach_retry_interval)
 | 
						|
            except wmi.x_wmi as exc:
 | 
						|
                LOG.debug("Attempt %(attempt)d to connect to target  "
 | 
						|
                          "%(target_iqn)s failed. Retrying. "
 | 
						|
                          "WMI exception: %(exc)s " %
 | 
						|
                          {'target_iqn': target_iqn,
 | 
						|
                           'exc': exc,
 | 
						|
                           'attempt': attempt})
 | 
						|
        raise vmutils.HyperVException(_('Failed to login target %s') %
 | 
						|
                                      target_iqn)
 | 
						|
 | 
						|
    def logout_storage_target(self, target_iqn):
 | 
						|
        """Logs out storage target through its session id."""
 | 
						|
        targets = self._conn_storage.MSFT_iSCSITarget(NodeAddress=target_iqn)
 | 
						|
        if targets:
 | 
						|
            target = targets[0]
 | 
						|
            if target.IsConnected:
 | 
						|
                sessions = self._conn_storage.MSFT_iSCSISession(
 | 
						|
                    TargetNodeAddress=target_iqn)
 | 
						|
 | 
						|
                for session in sessions:
 | 
						|
                    if session.IsPersistent:
 | 
						|
                        session.Unregister()
 | 
						|
 | 
						|
                target.Disconnect()
 | 
						|
 | 
						|
    def execute_log_out(self, session_id):
 | 
						|
        sessions = self._conn_wmi.MSiSCSIInitiator_SessionClass(
 | 
						|
            SessionId=session_id)
 | 
						|
        if sessions:
 | 
						|
            self.logout_storage_target(sessions[0].TargetName)
 |