Coverage for nova/virt/vmwareapi/session.py: 0%

63 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-17 15:08 +0000

1# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 

2# Copyright (c) 2012 VMware, Inc. 

3# Copyright (c) 2011 Citrix Systems, Inc. 

4# Copyright 2011 OpenStack Foundation 

5# 

6# Licensed under the Apache License, Version 2.0 (the "License"); you may 

7# not use this file except in compliance with the License. You may obtain 

8# a copy of the License at 

9# 

10# http://www.apache.org/licenses/LICENSE-2.0 

11# 

12# Unless required by applicable law or agreed to in writing, software 

13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

15# License for the specific language governing permissions and limitations 

16# under the License. 

17 

18import abc 

19import itertools 

20 

21from oslo_log import log as logging 

22from oslo_utils import excutils 

23from oslo_vmware import api 

24from oslo_vmware import exceptions as vexc 

25from oslo_vmware import vim 

26from oslo_vmware.vim_util import get_moref_value 

27 

28import nova.conf 

29 

30CONF = nova.conf.CONF 

31LOG = logging.getLogger(__name__) 

32 

33 

34class StableMoRefProxy(metaclass=abc.ABCMeta): 

35 """Abstract base class which acts as a proxy 

36 for Managed-Object-References (MoRef). 

37 Those references are usually "stable", meaning 

38 they don't change over the life-time of the object. 

39 But usually doesn't mean always. In that case, we 

40 need to fetch the reference again via some search method, 

41 which uses a guaranteed stable identifier (names, uuids, ...) 

42 """ 

43 

44 def __init__(self, ref): 

45 self.moref = ref 

46 

47 @property 

48 def __class__(self): 

49 # Suds accesses the __class__.__name__ attribute 

50 # of the object to determine the xml-tag of the object 

51 # so we have to fake it 

52 return self.moref.__class__ 

53 

54 @abc.abstractmethod 

55 def fetch_moref(self, session): 

56 """Updates the moref field or raises 

57 same exception the initial search would have 

58 """ 

59 

60 def __getattr__(self, name): 

61 return getattr(self.moref, name) 

62 

63 def __repr__(self): 

64 return "StableMoRefProxy({!r})".format(self.moref) 

65 

66 

67class MoRef(StableMoRefProxy): 

68 """MoRef takes a closure to resolve the reference of a managed object 

69 That closure is called again, in case we get a ManagedObjectNotFound 

70 exception on said reference. 

71 """ 

72 

73 def __init__(self, closure, ref=None): 

74 self._closure = closure 

75 ref = ref or self._closure() 

76 super().__init__(ref) 

77 

78 def fetch_moref(self, _): 

79 self.moref = self._closure() 

80 

81 def __repr__(self): 

82 return "MoRef({!r})".format(self.moref) 

83 

84 

85class VMwareAPISession(api.VMwareAPISession): 

86 """Sets up a session with the VC/ESX host and handles all 

87 the calls made to the host. 

88 """ 

89 

90 def __init__(self, host_ip=CONF.vmware.host_ip, 

91 host_port=CONF.vmware.host_port, 

92 username=CONF.vmware.host_username, 

93 password=CONF.vmware.host_password, 

94 retry_count=CONF.vmware.api_retry_count, 

95 scheme="https", 

96 cacert=CONF.vmware.ca_file, 

97 insecure=CONF.vmware.insecure, 

98 pool_size=CONF.vmware.connection_pool_size): 

99 super(VMwareAPISession, self).__init__( 

100 host=host_ip, 

101 port=host_port, 

102 server_username=username, 

103 server_password=password, 

104 api_retry_count=retry_count, 

105 task_poll_interval=CONF.vmware.task_poll_interval, 

106 scheme=scheme, 

107 create_session=True, 

108 cacert=cacert, 

109 insecure=insecure, 

110 pool_size=pool_size) 

111 

112 @staticmethod 

113 def _is_vim_object(module): 

114 """Check if the module is a VIM Object instance.""" 

115 return isinstance(module, vim.Vim) 

116 

117 def _call_method(self, module, method, *args, **kwargs): 

118 """Calls a method within the module specified with 

119 args provided. 

120 """ 

121 try: 

122 if not self._is_vim_object(module): 

123 return self.invoke_api(module, method, self.vim, *args, 

124 **kwargs) 

125 return self.invoke_api(module, method, *args, **kwargs) 

126 except vexc.ManagedObjectNotFoundException as monfe: 

127 with excutils.save_and_reraise_exception() as ctxt: 

128 moref = monfe.details.get("obj") if monfe.details else None 

129 for arg in itertools.chain(args, kwargs.values()): 

130 if not isinstance(arg, StableMoRefProxy): 

131 continue 

132 moref_arg = get_moref_value(arg.moref) 

133 if moref != moref_arg: 

134 continue 

135 # We have found the argument with the moref 

136 # causing the exception and we can try to recover it 

137 arg.fetch_moref(self) 

138 if not arg.moref: 

139 # We didn't recover the reference 

140 ctxt.reraise = True 

141 break 

142 moref_arg = get_moref_value(arg.moref) 

143 if moref != moref_arg: 

144 # We actually recovered, so do not raise `monfe` 

145 LOG.info("Replaced moref %s with %s", 

146 moref, moref_arg) 

147 ctxt.reraise = False 

148 # We only end up here when we have recovered a moref by changing 

149 # the stored value of an argument to a different value, 

150 # so let's try again (and recover again if it happens more than once) 

151 return self._call_method(module, method, *args, **kwargs) 

152 

153 def _wait_for_task(self, task_ref): 

154 """Return a Deferred that will give the result of the given task. 

155 The task is polled until it completes. 

156 """ 

157 return self.wait_for_task(task_ref)