1# All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may 4# not use this file except in compliance with the License. You may obtain 5# a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations 13# under the License. 14 15import sys 16import time 17 18from cinderclient import exceptions 19from cinderclient import utils 20 21_quota_resources = ['volumes', 'snapshots', 'gigabytes', 22 'backups', 'backup_gigabytes', 23 'per_volume_gigabytes', 'groups', ] 24_quota_infos = ['Type', 'In_use', 'Reserved', 'Limit', 'Allocated'] 25 26 27def print_volume_image(image_resp_tuple): 28 # image_resp_tuple = tuple (response, body) 29 image = image_resp_tuple[1] 30 vt = image['os-volume_upload_image'].get('volume_type') 31 if vt is not None: 32 image['os-volume_upload_image']['volume_type'] = vt.get('name') 33 utils.print_dict(image['os-volume_upload_image']) 34 35 36def poll_for_status(poll_fn, obj_id, action, final_ok_states, 37 poll_period=5, show_progress=True): 38 """Blocks while an action occurs. Periodically shows progress.""" 39 def print_progress(progress): 40 if show_progress: 41 msg = ('\rInstance %(action)s... %(progress)s%% complete' 42 % dict(action=action, progress=progress)) 43 else: 44 msg = '\rInstance %(action)s...' % dict(action=action) 45 46 sys.stdout.write(msg) 47 sys.stdout.flush() 48 49 print() 50 while True: 51 obj = poll_fn(obj_id) 52 status = obj.status.lower() 53 progress = getattr(obj, 'progress', None) or 0 54 if status in final_ok_states: 55 print_progress(100) 56 print("\nFinished") 57 break 58 elif status == "error": 59 print("\nError %(action)s instance" % {'action': action}) 60 break 61 else: 62 print_progress(progress) 63 time.sleep(poll_period) 64 65 66def find_volume_snapshot(cs, snapshot): 67 """Gets a volume snapshot by name or ID.""" 68 return utils.find_resource(cs.volume_snapshots, snapshot) 69 70 71def find_vtype(cs, vtype): 72 """Gets a volume type by name or ID.""" 73 return utils.find_resource(cs.volume_types, vtype) 74 75 76def find_gtype(cs, gtype): 77 """Gets a group type by name or ID.""" 78 return utils.find_resource(cs.group_types, gtype) 79 80 81def find_backup(cs, backup): 82 """Gets a backup by name or ID.""" 83 return utils.find_resource(cs.backups, backup) 84 85 86def find_consistencygroup(cs, consistencygroup): 87 """Gets a consistency group by name or ID.""" 88 return utils.find_resource(cs.consistencygroups, consistencygroup) 89 90 91def find_group(cs, group, **kwargs): 92 """Gets a group by name or ID.""" 93 kwargs['is_group'] = True 94 return utils.find_resource(cs.groups, group, **kwargs) 95 96 97def find_cgsnapshot(cs, cgsnapshot): 98 """Gets a cgsnapshot by name or ID.""" 99 return utils.find_resource(cs.cgsnapshots, cgsnapshot) 100 101 102def find_group_snapshot(cs, group_snapshot): 103 """Gets a group_snapshot by name or ID.""" 104 return utils.find_resource(cs.group_snapshots, group_snapshot) 105 106 107def find_transfer(cs, transfer): 108 """Gets a transfer by name or ID.""" 109 return utils.find_resource(cs.transfers, transfer) 110 111 112def find_qos_specs(cs, qos_specs): 113 """Gets a qos specs by ID.""" 114 return utils.find_resource(cs.qos_specs, qos_specs) 115 116 117def find_message(cs, message): 118 """Gets a message by ID.""" 119 return utils.find_resource(cs.messages, message) 120 121 122def print_volume_snapshot(snapshot): 123 utils.print_dict(snapshot._info) 124 125 126def translate_keys(collection, convert): 127 for item in collection: 128 keys = item.__dict__ 129 for from_key, to_key in convert: 130 if from_key in keys and to_key not in keys: 131 setattr(item, to_key, item._info[from_key]) 132 133 134def translate_volume_keys(collection): 135 convert = [('volumeType', 'volume_type'), 136 ('os-vol-tenant-attr:tenant_id', 'tenant_id')] 137 translate_keys(collection, convert) 138 139 140def translate_volume_snapshot_keys(collection): 141 convert = [('volumeId', 'volume_id')] 142 translate_keys(collection, convert) 143 144 145def translate_availability_zone_keys(collection): 146 convert = [('zoneName', 'name'), ('zoneState', 'status')] 147 translate_keys(collection, convert) 148 149 150def extract_filters(args): 151 filters = {} 152 for f in args: 153 if '=' in f: 154 (key, value) = f.split('=', 1) 155 if value.startswith('{') and value.endswith('}'): 156 value = _build_internal_dict(value[1:-1]) 157 filters[key] = value 158 else: 159 print("WARNING: Ignoring the filter %s while showing result." % f) 160 161 return filters 162 163 164def _build_internal_dict(content): 165 result = {} 166 for pair in content.split(','): 167 k, v = pair.split(':', 1) 168 result.update({k.strip(): v.strip()}) 169 return result 170 171 172def extract_metadata(args, type='user_metadata'): 173 metadata = {} 174 if type == 'image_metadata': 175 args_metadata = args.image_metadata 176 else: 177 args_metadata = args.metadata 178 for metadatum in args_metadata: 179 # unset doesn't require a val, so we have the if/else 180 if '=' in metadatum: 181 (key, value) = metadatum.split('=', 1) 182 else: 183 key = metadatum 184 value = None 185 186 metadata[key] = value 187 return metadata 188 189 190def print_volume_type_list(vtypes): 191 utils.print_list(vtypes, ['ID', 'Name', 'Description', 'Is_Public']) 192 193 194def print_group_type_list(gtypes): 195 utils.print_list(gtypes, ['ID', 'Name', 'Description']) 196 197 198def print_resource_filter_list(filters): 199 formatter = {'Filters': lambda resource: ', '.join(resource.filters)} 200 utils.print_list(filters, ['Resource', 'Filters'], formatters=formatter) 201 202 203def quota_show(quotas): 204 quotas_info_dict = utils.unicode_key_value_to_string(quotas._info) 205 quota_dict = {} 206 for resource in quotas_info_dict.keys(): 207 good_name = False 208 for name in _quota_resources: 209 if resource.startswith(name): 210 good_name = True 211 if not good_name: 212 continue 213 quota_dict[resource] = getattr(quotas, resource, None) 214 utils.print_dict(quota_dict) 215 216 217def quota_usage_show(quotas): 218 quota_list = [] 219 quotas_info_dict = utils.unicode_key_value_to_string(quotas._info) 220 for resource in quotas_info_dict.keys(): 221 good_name = False 222 for name in _quota_resources: 223 if resource.startswith(name): 224 good_name = True 225 if not good_name: 226 continue 227 quota_info = getattr(quotas, resource, None) 228 quota_info['Type'] = resource 229 quota_info = dict((k.capitalize(), v) for k, v in quota_info.items()) 230 quota_list.append(quota_info) 231 utils.print_list(quota_list, _quota_infos) 232 233 234def quota_update(manager, identifier, args): 235 updates = {} 236 for resource in _quota_resources: 237 val = getattr(args, resource, None) 238 if val is not None: 239 if args.volume_type: 240 resource = resource + '_%s' % args.volume_type 241 updates[resource] = val 242 243 if updates: 244 skip_validation = getattr(args, 'skip_validation', True) 245 if not skip_validation: 246 updates['skip_validation'] = skip_validation 247 quota_show(manager.update(identifier, **updates)) 248 else: 249 msg = 'Must supply at least one quota field to update.' 250 raise exceptions.ClientException(code=1, message=msg) 251 252 253def find_volume_type(cs, vtype): 254 """Gets a volume type by name or ID.""" 255 return utils.find_resource(cs.volume_types, vtype) 256 257 258def find_group_type(cs, gtype): 259 """Gets a group type by name or ID.""" 260 return utils.find_resource(cs.group_types, gtype) 261 262 263def print_volume_encryption_type_list(encryption_types): 264 """ 265 Lists volume encryption types. 266 267 :param encryption_types: a list of :class: VolumeEncryptionType instances 268 """ 269 utils.print_list(encryption_types, ['Volume Type ID', 'Provider', 270 'Cipher', 'Key Size', 271 'Control Location']) 272 273 274def print_qos_specs(qos_specs): 275 # formatters defines field to be converted from unicode to string 276 utils.print_dict(qos_specs._info, formatters=['specs']) 277 278 279def print_qos_specs_list(q_specs): 280 utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) 281 282 283def print_qos_specs_and_associations_list(q_specs): 284 utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) 285 286 287def print_associations_list(associations): 288 utils.print_list(associations, ['Association_Type', 'Name', 'ID']) 289 290 291def _poll_for_status(poll_fn, obj_id, info, action, final_ok_states, 292 timeout_period, global_request_id=None, messages=None, 293 poll_period=2, status_field="status"): 294 """Block while an action is being performed.""" 295 time_elapsed = 0 296 while True: 297 time.sleep(poll_period) 298 time_elapsed += poll_period 299 obj = poll_fn(obj_id) 300 status = getattr(obj, status_field) 301 info[status_field] = status 302 if status: 303 status = status.lower() 304 305 if status in final_ok_states: 306 break 307 elif status == "error": 308 utils.print_dict(info) 309 if global_request_id: 310 search_opts = { 311 'request_id': global_request_id 312 } 313 message_list = messages.list(search_opts=search_opts) 314 try: 315 fault_msg = message_list[0].user_message 316 except IndexError: 317 fault_msg = "Unknown error. Operation failed." 318 raise exceptions.ResourceInErrorState(obj, fault_msg) 319 elif time_elapsed == timeout_period: 320 utils.print_dict(info) 321 raise exceptions.TimeoutException(obj, action) 322