| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | ## |
| 3 | # This file is standalone vmware vcloud director util |
| 4 | # All Rights Reserved. |
| 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 | # |
| 18 | # For those usages not covered by the Apache License, Version 2.0 please |
| 19 | # contact with: mbayramov@vmware.com |
| 20 | ## |
| 21 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 22 | """ |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 23 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 24 | Standalone application that leverage openmano vmware connector work with vCloud director rest api. |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 25 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 26 | - Provides capability to create and delete VDC for specific organization. |
| 27 | - Create, delete and manage network for specific VDC |
| 28 | - List deployed VM's , VAPPs, VDSs, Organization |
| 29 | - View detail information about VM / Vapp , Organization etc |
| 30 | - Operate with images upload / boot / power on etc |
| 31 | |
| 32 | Usage example. |
| 33 | |
| 34 | List organization created in vCloud director |
| 35 | vmwarecli.py -u admin -p qwerty123 -c 172.16.254.206 -U Administrator -P qwerty123 -o test -v TEF list org |
| 36 | |
| 37 | List VDC for particular organization |
| 38 | vmwarecli.py -u admin -p qwerty123 -c 172.16.254.206 -U Administrator -P qwerty123 -o test -v TEF list vdc |
| 39 | |
| 40 | Upload image |
| 41 | python vmwarerecli.py image upload /Users/spyroot/Developer/Openmano/Ro/vnfs/cirros/cirros.ovf |
| 42 | |
| 43 | Boot Image |
| 44 | python vmwarerecli.py -u admin -p qwerty123 -c 172.16.254.206 -o test -v TEF image boot cirros cirros |
| 45 | |
| 46 | View vApp |
| 47 | python vmwarerecli.py -u admin -p qwerty123 -c 172.16.254.206 -o test -v TEF view vapp 90bd2b4e-f782-46cf-b5e2-c3817dcf6633 -u |
| 48 | |
| 49 | List VMS |
| 50 | python vmwarerecli.py -u admin -p qwerty123 -c 172.16.254.206 -o test -v TEF list vms |
| 51 | |
| 52 | List VDC in OSM format |
| 53 | python vmwarerecli.py -u admin -p qwerty123 -c 172.16.254.206 -o test -v TEF list vdc -o |
| 54 | |
| 55 | Mustaafa Bayramov |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 56 | mbayramov@vmware.com |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 57 | """ |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 58 | import os |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 59 | import argparse |
| 60 | import traceback |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 61 | import uuid |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 62 | |
| 63 | from xml.etree import ElementTree as ET |
| 64 | |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 65 | import sys |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 66 | from pyvcloud import Http |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 67 | |
| 68 | import logging |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 69 | import vimconn |
| 70 | import time |
| 71 | import uuid |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 72 | import urllib3 |
| 73 | import requests |
| 74 | |
| 75 | from vimconn_vmware import vimconnector |
| 76 | from requests.packages.urllib3.exceptions import InsecureRequestWarning |
| 77 | from prettytable import PrettyTable |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 78 | |
| 79 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) |
| 80 | |
| 81 | __author__ = "Mustafa Bayramov" |
| 82 | __date__ = "$16-Sep-2016 11:09:29$" |
| 83 | |
| 84 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 85 | # TODO move to main vim |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 86 | def delete_network_action(vca=None, network_uuid=None): |
| 87 | """ |
| 88 | Method leverages vCloud director and query network based on network uuid |
| 89 | |
| 90 | Args: |
| 91 | vca - is active VCA connection. |
| 92 | network_uuid - is a network uuid |
| 93 | |
| 94 | Returns: |
| 95 | The return XML respond |
| 96 | """ |
| 97 | |
| 98 | if vca is None or network_uuid is None: |
| 99 | return None |
| 100 | |
| 101 | url_list = [vca.host, '/api/admin/network/', network_uuid] |
| 102 | vm_list_rest_call = ''.join(url_list) |
| 103 | |
| 104 | if not (not vca.vcloud_session or not vca.vcloud_session.organization): |
| 105 | response = Http.get(url=vm_list_rest_call, |
| 106 | headers=vca.vcloud_session.get_vcloud_headers(), |
| 107 | verify=vca.verify, |
| 108 | logger=vca.logger) |
| 109 | if response.status_code == requests.codes.ok: |
| 110 | print response.content |
| 111 | return response.content |
| 112 | |
| 113 | return None |
| 114 | |
| 115 | |
| 116 | def print_vapp(vapp_dict=None): |
| 117 | """ Method takes vapp_dict and print in tabular format |
| 118 | |
| 119 | Args: |
| 120 | vapp_dict: container vapp object. |
| 121 | |
| 122 | Returns: |
| 123 | The return nothing |
| 124 | """ |
| 125 | |
| 126 | # following key available to print |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 127 | # {'status': 'POWERED_OFF', 'storageProfileName': '*', 'hardwareVersion': '7', 'vmToolsVersion': '0', |
| 128 | # 'memoryMB': '384', |
| 129 | # 'href': 'https://172.16.254.206/api/vAppTemplate/vm-129e22e8-08dc-4cb6-8358-25f635e65d3b', |
| 130 | # 'isBusy': 'false', 'isDeployed': 'false', 'isInMaintenanceMode': 'false', 'isVAppTemplate': 'true', |
| 131 | # 'networkName': 'nat', 'isDeleted': 'false', 'catalogName': 'Cirros', |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 132 | # 'containerName': 'Cirros Template', # 'container': |
| 133 | # 'https://172.16.254.206/api/vAppTemplate/vappTemplate-b966453d-c361-4505-9e38-ccef45815e5d', |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 134 | # 'name': 'Cirros', 'pvdcHighestSupportedHardwareVersion': '11', 'isPublished': 'false', |
| 135 | # 'numberOfCpus': '1', 'vdc': 'https://172.16.254.206/api/vdc/a5056f85-418c-4bfd-8041-adb0f48be9d9', |
| 136 | # 'guestOs': 'Other (32-bit)', 'isVdcEnabled': 'true'} |
| 137 | |
| 138 | if vapp_dict is None: |
| 139 | return |
| 140 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 141 | vm_table = PrettyTable(['vm uuid', |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 142 | 'vapp name', |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 143 | 'vapp uuid', |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 144 | 'network name', |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 145 | 'storage name', |
| 146 | 'vcpu', 'memory', 'hw ver','deployed','status']) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 147 | for k in vapp_dict: |
| 148 | entry = [] |
| 149 | entry.append(k) |
| 150 | entry.append(vapp_dict[k]['containerName']) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 151 | # vm-b1f5cd4c-2239-4c89-8fdc-a41ff18e0d61 |
| 152 | entry.append(vapp_dict[k]['container'].split('/')[-1:][0][5:]) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 153 | entry.append(vapp_dict[k]['networkName']) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 154 | entry.append(vapp_dict[k]['storageProfileName']) |
| 155 | entry.append(vapp_dict[k]['numberOfCpus']) |
| 156 | entry.append(vapp_dict[k]['memoryMB']) |
| 157 | entry.append(vapp_dict[k]['pvdcHighestSupportedHardwareVersion']) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 158 | entry.append(vapp_dict[k]['isDeployed']) |
| 159 | entry.append(vapp_dict[k]['status']) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 160 | |
| 161 | vm_table.add_row(entry) |
| 162 | |
| 163 | print vm_table |
| 164 | |
| 165 | |
| 166 | def print_org(org_dict=None): |
| 167 | """ Method takes vapp_dict and print in tabular format |
| 168 | |
| 169 | Args: |
| 170 | org_dict: dictionary of organization where key is org uuid. |
| 171 | |
| 172 | Returns: |
| 173 | The return nothing |
| 174 | """ |
| 175 | |
| 176 | if org_dict is None: |
| 177 | return |
| 178 | |
| 179 | org_table = PrettyTable(['org uuid', 'name']) |
| 180 | for k in org_dict: |
| 181 | entry = [k, org_dict[k]] |
| 182 | org_table.add_row(entry) |
| 183 | |
| 184 | print org_table |
| 185 | |
| 186 | |
| 187 | def print_vm_list(vm_dict=None): |
| 188 | """ Method takes vapp_dict and print in tabular format |
| 189 | |
| 190 | Args: |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 191 | vm_dict: dictionary of organization where key is org uuid. |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 192 | |
| 193 | Returns: |
| 194 | The return nothing |
| 195 | """ |
| 196 | if vm_dict is None: |
| 197 | return |
| 198 | |
| 199 | vm_table = PrettyTable( |
| 200 | ['vm uuid', 'vm name', 'vapp uuid', 'vdc uuid', 'network name', 'is deployed', 'vcpu', 'memory', 'status']) |
| 201 | |
| 202 | try: |
| 203 | for k in vm_dict: |
| 204 | entry = [] |
| 205 | entry.append(k) |
| 206 | entry.append(vm_dict[k]['name']) |
| 207 | entry.append(vm_dict[k]['container'].split('/')[-1:][0][5:]) |
| 208 | entry.append(vm_dict[k]['vdc'].split('/')[-1:][0]) |
| 209 | entry.append(vm_dict[k]['networkName']) |
| 210 | entry.append(vm_dict[k]['isDeployed']) |
| 211 | entry.append(vm_dict[k]['numberOfCpus']) |
| 212 | entry.append(vm_dict[k]['memoryMB']) |
| 213 | entry.append(vm_dict[k]['status']) |
| 214 | vm_table.add_row(entry) |
| 215 | print vm_table |
| 216 | except KeyError: |
| 217 | logger.error("wrong key {}".format(KeyError.message)) |
| 218 | pass |
| 219 | |
| 220 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 221 | def print_vdc_list(org_dict=None): |
| 222 | """ Method takes vapp_dict and print in tabular format |
| 223 | |
| 224 | Args: |
| 225 | org_dict: dictionary of organization where key is org uuid. |
| 226 | |
| 227 | Returns: |
| 228 | The return nothing |
| 229 | """ |
| 230 | if org_dict is None: |
| 231 | return |
| 232 | try: |
| 233 | vdcs_dict = {} |
| 234 | if org_dict.has_key('vdcs'): |
| 235 | vdcs_dict = org_dict['vdcs'] |
| 236 | vdc_table = PrettyTable(['vdc uuid', 'vdc name']) |
| 237 | for k in vdcs_dict: |
| 238 | entry = [k, vdcs_dict[k]] |
| 239 | vdc_table.add_row(entry) |
| 240 | |
| 241 | print vdc_table |
| 242 | except KeyError: |
| 243 | logger.error("wrong key {}".format(KeyError.message)) |
| 244 | logger.logger.debug(traceback.format_exc()) |
| 245 | |
| 246 | |
| 247 | def print_network_list(org_dict=None): |
| 248 | """ Method print network list. |
| 249 | |
| 250 | Args: |
| 251 | org_dict: dictionary of organization that contain key networks with a list of all |
| 252 | network for for specific VDC |
| 253 | |
| 254 | Returns: |
| 255 | The return nothing |
| 256 | """ |
| 257 | if org_dict is None: |
| 258 | return |
| 259 | try: |
| 260 | network_dict = {} |
| 261 | if org_dict.has_key('networks'): |
| 262 | network_dict = org_dict['networks'] |
| 263 | network_table = PrettyTable(['network uuid', 'network name']) |
| 264 | for k in network_dict: |
| 265 | entry = [k, network_dict[k]] |
| 266 | network_table.add_row(entry) |
| 267 | |
| 268 | print network_table |
| 269 | |
| 270 | except KeyError: |
| 271 | logger.error("wrong key {}".format(KeyError.message)) |
| 272 | logger.logger.debug(traceback.format_exc()) |
| 273 | |
| 274 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 275 | def print_org_details(org_dict=None): |
| 276 | """ Method takes vapp_dict and print in tabular format |
| 277 | |
| 278 | Args: |
| 279 | org_dict: dictionary of organization where key is org uuid. |
| 280 | |
| 281 | Returns: |
| 282 | The return nothing |
| 283 | """ |
| 284 | if org_dict is None: |
| 285 | return |
| 286 | try: |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 287 | catalogs_dict = {} |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 288 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 289 | print_vdc_list(org_dict=org_dict) |
| 290 | print_network_list(org_dict=org_dict) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 291 | |
| 292 | if org_dict.has_key('catalogs'): |
| 293 | catalogs_dict = org_dict['catalogs'] |
| 294 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 295 | catalog_table = PrettyTable(['catalog uuid', 'catalog name']) |
| 296 | for k in catalogs_dict: |
| 297 | entry = [k, catalogs_dict[k]] |
| 298 | catalog_table.add_row(entry) |
| 299 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 300 | print catalog_table |
| 301 | |
| 302 | except KeyError: |
| 303 | logger.error("wrong key {}".format(KeyError.message)) |
| 304 | logger.logger.debug(traceback.format_exc()) |
| 305 | |
| 306 | |
| 307 | def delete_actions(vim=None, action=None, namespace=None): |
| 308 | if action == 'network' or namespace.action == 'network': |
| 309 | logger.debug("Requesting delete for network {}".format(namespace.network_name)) |
| 310 | network_uuid = namespace.network_name |
| 311 | # if request name based we need find UUID |
| 312 | # TODO optimize it or move to external function |
| 313 | if not namespace.uuid: |
| 314 | org_dict = vim.get_org_list() |
| 315 | for org in org_dict: |
| 316 | org_net = vim.get_org(org)['networks'] |
| 317 | for network in org_net: |
| 318 | if org_net[network] == namespace.network_name: |
| 319 | network_uuid = network |
| 320 | |
| 321 | vim.delete_network_action(network_uuid=network_uuid) |
| 322 | |
| 323 | |
| 324 | def list_actions(vim=None, action=None, namespace=None): |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 325 | """ Method provide list object from VDC action |
| 326 | |
| 327 | Args: |
| 328 | vim - is vcloud director vim connector. |
| 329 | action - is action for list ( vdc / org etc) |
| 330 | namespace - must contain VDC / Org information. |
| 331 | |
| 332 | Returns: |
| 333 | The return nothing |
| 334 | """ |
| 335 | |
| 336 | org_id = None |
| 337 | myorgs = vim.get_org_list() |
| 338 | for org in myorgs: |
| 339 | if myorgs[org] == namespace.vcdorg: |
| 340 | org_id = org |
| 341 | break |
| 342 | else: |
| 343 | print(" Invalid organization.") |
| 344 | return |
| 345 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 346 | if action == 'vms' or namespace.action == 'vms': |
| 347 | vm_dict = vim.get_vm_list(vdc_name=namespace.vcdvdc) |
| 348 | print_vm_list(vm_dict=vm_dict) |
| 349 | elif action == 'vapps' or namespace.action == 'vapps': |
| 350 | vapp_dict = vim.get_vapp_list(vdc_name=namespace.vcdvdc) |
| 351 | print_vapp(vapp_dict=vapp_dict) |
| 352 | elif action == 'networks' or namespace.action == 'networks': |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 353 | if namespace.osm: |
| 354 | osm_print(vim.get_network_list(filter_dict={})) |
| 355 | else: |
| 356 | print_network_list(vim.get_org(org_uuid=org_id)) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 357 | elif action == 'vdc' or namespace.action == 'vdc': |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 358 | if namespace.osm: |
| 359 | osm_print(vim.get_tenant_list(filter_dict=None)) |
| 360 | else: |
| 361 | print_vdc_list(vim.get_org(org_uuid=org_id)) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 362 | elif action == 'org' or namespace.action == 'org': |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 363 | print_org(org_dict=vim.get_org_list()) |
| 364 | else: |
| 365 | return None |
| 366 | |
| 367 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 368 | def print_network_details(network_dict=None): |
| 369 | try: |
| 370 | network_table = PrettyTable(network_dict.keys()) |
| 371 | entry = [network_dict.values()] |
| 372 | network_table.add_row(entry[0]) |
| 373 | print network_table |
| 374 | except KeyError: |
| 375 | logger.error("wrong key {}".format(KeyError.message)) |
| 376 | logger.logger.debug(traceback.format_exc()) |
| 377 | |
| 378 | |
| 379 | def osm_print(generic_dict=None): |
| 380 | |
| 381 | try: |
| 382 | for element in generic_dict: |
| 383 | table = PrettyTable(element.keys()) |
| 384 | entry = [element.values()] |
| 385 | table.add_row(entry[0]) |
| 386 | print table |
| 387 | except KeyError: |
| 388 | logger.error("wrong key {}".format(KeyError.message)) |
| 389 | logger.logger.debug(traceback.format_exc()) |
| 390 | |
| 391 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 392 | def view_actions(vim=None, action=None, namespace=None): |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 393 | org_id = None |
| 394 | orgs = vim.get_org_list() |
| 395 | for org in orgs: |
| 396 | if orgs[org] == namespace.vcdorg: |
| 397 | org_id = org |
| 398 | break |
| 399 | else: |
| 400 | print(" Invalid organization.") |
| 401 | return |
| 402 | |
| 403 | myorg = vim.get_org(org_uuid=org_id) |
| 404 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 405 | # view org |
| 406 | if action == 'org' or namespace.action == 'org': |
| 407 | org_id = None |
| 408 | orgs = vim.get_org_list() |
| 409 | if namespace.uuid: |
| 410 | if namespace.org_name in orgs: |
| 411 | org_id = namespace.org_name |
| 412 | else: |
| 413 | # we need find UUID based on name provided |
| 414 | for org in orgs: |
| 415 | if orgs[org] == namespace.org_name: |
| 416 | org_id = org |
| 417 | break |
| 418 | |
| 419 | logger.debug("Requesting view for orgs {}".format(org_id)) |
| 420 | print_org_details(vim.get_org(org_uuid=org_id)) |
| 421 | |
| 422 | # view vapp action |
| 423 | if action == 'vapp' or namespace.action == 'vapp': |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 424 | if namespace.vapp_name is not None and namespace.uuid: |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 425 | logger.debug("Requesting vapp {} for vdc {}".format(namespace.vapp_name, namespace.vcdvdc)) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 426 | vapp_dict = {} |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 427 | vapp_uuid = namespace.vapp_name |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 428 | # if request based on just name we need get UUID |
| 429 | if not namespace.uuid: |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 430 | vapp_uuid = vim.get_vappid(vdc=namespace.vcdvdc, vapp_name=namespace.vapp_name) |
| 431 | if vapp_uuid is None: |
| 432 | print("Can't find vapp by given name {}".format(namespace.vapp_name)) |
| 433 | return |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 434 | |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 435 | print " namespace {}".format(namespace) |
| 436 | if vapp_dict is not None and namespace.osm: |
| 437 | vm_info_dict = vim.get_vminstance(vim_vm_uuid=vapp_uuid) |
| 438 | print vm_info_dict |
| 439 | if vapp_dict is not None and namespace.osm != True: |
| 440 | vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vapp_uuid, isuuid=True) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 441 | print_vapp(vapp_dict=vapp_dict) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 442 | |
| 443 | # view network |
| 444 | if action == 'network' or namespace.action == 'network': |
| 445 | logger.debug("Requesting view for network {}".format(namespace.network_name)) |
| 446 | network_uuid = namespace.network_name |
| 447 | # if request name based we need find UUID |
| 448 | # TODO optimize it or move to external function |
| 449 | if not namespace.uuid: |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 450 | if not myorg.has_key('networks'): |
| 451 | print("Network {} is undefined in vcloud director for org {} vdc {}".format(namespace.network_name, |
| 452 | vim.name, |
| 453 | vim.tenant_name)) |
| 454 | return |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 455 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 456 | my_org_net = myorg['networks'] |
| 457 | for network in my_org_net: |
| 458 | if my_org_net[network] == namespace.network_name: |
| 459 | network_uuid = network |
| 460 | break |
| 461 | |
| 462 | print print_network_details(network_dict=vim.get_vcd_network(network_uuid=network_uuid)) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 463 | |
| 464 | |
| 465 | def create_actions(vim=None, action=None, namespace=None): |
| 466 | """Method gets provider vdc view from vcloud director |
| 467 | |
| 468 | Args: |
| 469 | vim - is Cloud director vim connector |
| 470 | action - action for create ( network / vdc etc) |
| 471 | |
| 472 | Returns: |
| 473 | The return xml content of respond or None |
| 474 | """ |
| 475 | if action == 'network' or namespace.action == 'network': |
| 476 | logger.debug("Creating a network in vcloud director".format(namespace.network_name)) |
| 477 | network_uuid = vim.create_network(namespace.network_name) |
| 478 | if network_uuid is not None: |
| 479 | print ("Crated new network {} and uuid: {}".format(namespace.network_name, network_uuid)) |
| 480 | else: |
| 481 | print ("Failed create a new network {}".format(namespace.network_name)) |
| 482 | elif action == 'vdc' or namespace.action == 'vdc': |
| 483 | logger.debug("Creating a new vdc in vcloud director.".format(namespace.vdc_name)) |
| 484 | vdc_uuid = vim.create_vdc(namespace.vdc_name) |
| 485 | if vdc_uuid is not None: |
| 486 | print ("Crated new vdc {} and uuid: {}".format(namespace.vdc_name, vdc_uuid)) |
| 487 | else: |
| 488 | print ("Failed create a new vdc {}".format(namespace.vdc_name)) |
| 489 | else: |
| 490 | return None |
| 491 | |
| 492 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 493 | def validate_uuid4(uuid_string): |
| 494 | """Function validate that string contain valid uuid4 |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 495 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 496 | Args: |
| 497 | uuid_string - valid UUID string |
| 498 | |
| 499 | Returns: |
| 500 | The return true if string contain valid UUID format |
| 501 | """ |
| 502 | try: |
| 503 | val = uuid.UUID(uuid_string, version=4) |
| 504 | except ValueError: |
| 505 | return False |
| 506 | return True |
| 507 | |
| 508 | |
| 509 | def upload_image(vim=None, image_file=None): |
| 510 | """Function upload image to vcloud director |
| 511 | |
| 512 | Args: |
| 513 | image_file - valid UUID string |
| 514 | |
| 515 | Returns: |
| 516 | The return true if image uploaded correctly |
| 517 | """ |
| 518 | try: |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 519 | catalog_uuid = vim.get_image_id_from_path(path=image_file, progress=True) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 520 | if catalog_uuid is not None and validate_uuid4(catalog_uuid): |
| 521 | print("Image uploaded and uuid {}".format(catalog_uuid)) |
| 522 | return True |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 523 | except vimconn.vimconnException as upload_exception: |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 524 | print("Failed uploaded {} image".format(image_file)) |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 525 | print("Error Reason: {}".format(upload_exception.message)) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 526 | return False |
| 527 | |
| 528 | |
| 529 | def boot_image(vim=None, image_name=None, vm_name=None): |
| 530 | """ Function boot image that resided in vcloud director. |
| 531 | The image name can be UUID of name. |
| 532 | |
| 533 | Args: |
| bayramov | 163f1ae | 2016-09-28 17:16:55 +0400 | [diff] [blame] | 534 | vim - vim connector |
| 535 | image_name - image identified by UUID or text string. |
| 536 | vm_name - vmname |
| 537 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 538 | |
| 539 | Returns: |
| 540 | The return true if image uploaded correctly |
| 541 | """ |
| 542 | |
| 543 | vim_catalog = None |
| 544 | try: |
| 545 | catalogs = vim.vca.get_catalogs() |
| 546 | if not validate_uuid4(image_name): |
| 547 | vim_catalog = vim.get_catalogid(catalog_name=image_name, catalogs=catalogs) |
| 548 | if vim_catalog is None: |
| 549 | return None |
| 550 | else: |
| 551 | vim_catalog = vim.get_catalogid(catalog_name=image_name, catalogs=catalogs) |
| 552 | if vim_catalog is None: |
| 553 | return None |
| 554 | |
| bayramov | 5761ad1 | 2016-10-04 09:00:30 +0400 | [diff] [blame] | 555 | print (" Booting {} image id {} ".format(vm_name, vim_catalog)) |
| tierno | 98e909c | 2017-10-14 13:27:03 +0200 | [diff] [blame] | 556 | vm_uuid, _ = vim.new_vminstance(name=vm_name, image_id=vim_catalog) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 557 | if vm_uuid is not None and validate_uuid4(vm_uuid): |
| 558 | print("Image booted and vm uuid {}".format(vm_uuid)) |
| 559 | vapp_dict = vim.get_vapp(vdc_name=namespace.vcdvdc, vapp_name=vm_uuid, isuuid=True) |
| 560 | if vapp_dict is not None: |
| 561 | print_vapp(vapp_dict=vapp_dict) |
| 562 | return True |
| bayramov | 5761ad1 | 2016-10-04 09:00:30 +0400 | [diff] [blame] | 563 | except vimconn.vimconnNotFoundException as notFound: |
| 564 | print("Failed boot {} image".format(image_name)) |
| 565 | print(notFound.message) |
| 566 | except vimconn.vimconnException as vimconError: |
| 567 | print("Failed boot {} image".format(image_name)) |
| 568 | print(vimconError.message) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 569 | except: |
| bayramov | 5761ad1 | 2016-10-04 09:00:30 +0400 | [diff] [blame] | 570 | print("Failed boot {} image".format(image_name)) |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 571 | |
| bayramov | 5761ad1 | 2016-10-04 09:00:30 +0400 | [diff] [blame] | 572 | |
| 573 | return False |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 574 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 575 | |
| 576 | def image_action(vim=None, action=None, namespace=None): |
| 577 | """ Function present set of action to manipulate with image. |
| 578 | - upload image |
| 579 | - boot image. |
| 580 | - delete image ( not yet done ) |
| 581 | |
| 582 | Args: |
| 583 | vim - vcloud director connector |
| 584 | action - string (upload/boot etc) |
| 585 | namespace - contain other attributes image name etc |
| 586 | |
| 587 | Returns: |
| 588 | The return nothing |
| 589 | """ |
| 590 | |
| 591 | if action == 'upload' or namespace.action == 'upload': |
| 592 | upload_image(vim=vim, image_file=namespace.image) |
| 593 | elif action == 'boot' or namespace.action == 'boot': |
| 594 | boot_image(vim=vim, image_name=namespace.image, vm_name=namespace.vmname) |
| 595 | else: |
| 596 | return None |
| 597 | |
| 598 | |
| 599 | def vmwarecli(command=None, action=None, namespace=None): |
| bayramov | a09cf38 | 2016-09-28 04:13:46 +0400 | [diff] [blame] | 600 | logger.debug("Namespace {}".format(namespace)) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 601 | urllib3.disable_warnings() |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 602 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 603 | vcduser = None |
| 604 | vcdpasword = None |
| 605 | vcdhost = None |
| 606 | vcdorg = None |
| 607 | |
| 608 | if hasattr(__builtins__, 'raw_input'): |
| 609 | input = raw_input |
| 610 | |
| 611 | if namespace.vcdvdc is None: |
| 612 | while True: |
| 613 | vcduser = input("Enter vcd username: ") |
| 614 | if vcduser is not None and len(vcduser) > 0: |
| 615 | break |
| 616 | else: |
| 617 | vcduser = namespace.vcduser |
| 618 | |
| bayramov | a09cf38 | 2016-09-28 04:13:46 +0400 | [diff] [blame] | 619 | if namespace.vcdpassword is None: |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 620 | while True: |
| 621 | vcdpasword = input("Please enter vcd password: ") |
| 622 | if vcdpasword is not None and len(vcdpasword) > 0: |
| 623 | break |
| bayramov | a09cf38 | 2016-09-28 04:13:46 +0400 | [diff] [blame] | 624 | else: |
| 625 | vcdpasword = namespace.vcdpassword |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 626 | |
| 627 | if namespace.vcdhost is None: |
| 628 | while True: |
| 629 | vcdhost = input("Please enter vcd host name or ip: ") |
| 630 | if vcdhost is not None and len(vcdhost) > 0: |
| 631 | break |
| 632 | else: |
| 633 | vcdhost = namespace.vcdhost |
| 634 | |
| 635 | if namespace.vcdorg is None: |
| 636 | while True: |
| 637 | vcdorg = input("Please enter vcd organization name: ") |
| 638 | if vcdorg is not None and len(vcdorg) > 0: |
| 639 | break |
| 640 | else: |
| 641 | vcdorg = namespace.vcdorg |
| 642 | |
| 643 | try: |
| 644 | vim = vimconnector(uuid=None, |
| 645 | name=vcdorg, |
| 646 | tenant_id=None, |
| 647 | tenant_name=namespace.vcdvdc, |
| 648 | url=vcdhost, |
| 649 | url_admin=vcdhost, |
| 650 | user=vcduser, |
| 651 | passwd=vcdpasword, |
| 652 | log_level="DEBUG", |
| 653 | config={'admin_username': namespace.vcdamdin, 'admin_password': namespace.vcdadminpassword}) |
| 654 | vim.vca = vim.connect() |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 655 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 656 | except vimconn.vimconnConnectionException: |
| 657 | print("Failed connect to vcloud director. Please check credential and hostname.") |
| 658 | return |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 659 | |
| 660 | # list |
| 661 | if command == 'list' or namespace.command == 'list': |
| 662 | logger.debug("Client requested list action") |
| 663 | # route request to list actions |
| 664 | list_actions(vim=vim, action=action, namespace=namespace) |
| 665 | |
| 666 | # view action |
| 667 | if command == 'view' or namespace.command == 'view': |
| 668 | logger.debug("Client requested view action") |
| 669 | view_actions(vim=vim, action=action, namespace=namespace) |
| 670 | |
| 671 | # delete action |
| 672 | if command == 'delete' or namespace.command == 'delete': |
| 673 | logger.debug("Client requested delete action") |
| 674 | delete_actions(vim=vim, action=action, namespace=namespace) |
| 675 | |
| 676 | # create action |
| 677 | if command == 'create' or namespace.command == 'create': |
| 678 | logger.debug("Client requested create action") |
| 679 | create_actions(vim=vim, action=action, namespace=namespace) |
| 680 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 681 | # image action |
| 682 | if command == 'image' or namespace.command == 'image': |
| 683 | logger.debug("Client requested create action") |
| 684 | image_action(vim=vim, action=action, namespace=namespace) |
| 685 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 686 | |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 687 | if __name__ == '__main__': |
| 688 | defaults = {'vcdvdc': 'default', |
| 689 | 'vcduser': 'admin', |
| 690 | 'vcdpassword': 'admin', |
| 691 | 'vcdhost': 'https://localhost', |
| 692 | 'vcdorg': 'default', |
| 693 | 'debug': 'INFO'} |
| 694 | |
| 695 | parser = argparse.ArgumentParser() |
| 696 | parser.add_argument('-u', '--vcduser', help='vcloud director username', type=str) |
| 697 | parser.add_argument('-p', '--vcdpassword', help='vcloud director password', type=str) |
| bayramov | a09cf38 | 2016-09-28 04:13:46 +0400 | [diff] [blame] | 698 | parser.add_argument('-U', '--vcdamdin', help='vcloud director password', type=str) |
| 699 | parser.add_argument('-P', '--vcdadminpassword', help='vcloud director password', type=str) |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 700 | parser.add_argument('-c', '--vcdhost', help='vcloud director host', type=str) |
| 701 | parser.add_argument('-o', '--vcdorg', help='vcloud director org', type=str) |
| 702 | parser.add_argument('-v', '--vcdvdc', help='vcloud director vdc', type=str) |
| 703 | parser.add_argument('-d', '--debug', help='debug level', type=int) |
| 704 | |
| 705 | parser_subparsers = parser.add_subparsers(help='commands', dest='command') |
| 706 | sub = parser_subparsers.add_parser('list', help='List objects (VMs, vApps, networks)') |
| 707 | sub_subparsers = sub.add_subparsers(dest='action') |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 708 | |
| 709 | list_vms = sub_subparsers.add_parser('vms', help='list - all vm deployed in vCloud director') |
| 710 | list_vapps = sub_subparsers.add_parser('vapps', help='list - all vapps deployed in vCloud director') |
| 711 | list_network = sub_subparsers.add_parser('networks', help='list - all networks deployed') |
| 712 | list_network.add_argument('-o', '--osm', default=False, action='store_true', help='provide view in OSM format') |
| 713 | |
| 714 | #list vdc |
| 715 | list_vdc = sub_subparsers.add_parser('vdc', help='list - list all vdc for organization accessible to you') |
| 716 | list_vdc.add_argument('-o', '--osm', default=False, action='store_true', help='provide view in OSM format') |
| 717 | |
| 718 | list_org = sub_subparsers.add_parser('org', help='list - list of organizations accessible to you.') |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 719 | |
| 720 | create_sub = parser_subparsers.add_parser('create') |
| 721 | create_sub_subparsers = create_sub.add_subparsers(dest='action') |
| 722 | create_vms = create_sub_subparsers.add_parser('vms') |
| 723 | create_vapp = create_sub_subparsers.add_parser('vapp') |
| 724 | create_vapp.add_argument('uuid') |
| 725 | |
| 726 | # add network |
| 727 | create_network = create_sub_subparsers.add_parser('network') |
| 728 | create_network.add_argument('network_name', action='store', help='create a network for a vdc') |
| 729 | |
| 730 | # add VDC |
| 731 | create_vdc = create_sub_subparsers.add_parser('vdc') |
| 732 | create_vdc.add_argument('vdc_name', action='store', help='create a new VDC for org') |
| 733 | |
| 734 | delete_sub = parser_subparsers.add_parser('delete') |
| 735 | del_sub_subparsers = delete_sub.add_subparsers(dest='action') |
| 736 | del_vms = del_sub_subparsers.add_parser('vms') |
| 737 | del_vapp = del_sub_subparsers.add_parser('vapp') |
| 738 | del_vapp.add_argument('uuid', help='view vapp based on UUID') |
| 739 | |
| 740 | # delete network |
| 741 | del_network = del_sub_subparsers.add_parser('network') |
| 742 | del_network.add_argument('network_name', action='store', |
| 743 | help='- delete network for vcloud director by provided name') |
| 744 | del_network.add_argument('-u', '--uuid', default=False, action='store_true', |
| 745 | help='delete network for vcloud director by provided uuid') |
| 746 | |
| 747 | # delete vdc |
| 748 | del_vdc = del_sub_subparsers.add_parser('vdc') |
| 749 | |
| 750 | view_sub = parser_subparsers.add_parser('view') |
| 751 | view_sub_subparsers = view_sub.add_subparsers(dest='action') |
| 752 | |
| 753 | view_vms_parser = view_sub_subparsers.add_parser('vms') |
| 754 | view_vms_parser.add_argument('uuid', default=False, action='store_true', |
| 755 | help='- View VM for specific uuid in vcloud director') |
| 756 | view_vms_parser.add_argument('name', default=False, action='store_true', |
| 757 | help='- View VM for specific vapp name in vcloud director') |
| 758 | |
| 759 | # view vapp |
| 760 | view_vapp_parser = view_sub_subparsers.add_parser('vapp') |
| 761 | view_vapp_parser.add_argument('vapp_name', action='store', |
| 762 | help='- view vapp for specific vapp name in vcloud director') |
| 763 | view_vapp_parser.add_argument('-u', '--uuid', default=False, action='store_true', help='view vapp based on uuid') |
| bayramov | fe3f3c9 | 2016-10-04 07:53:41 +0400 | [diff] [blame] | 764 | view_vapp_parser.add_argument('-o', '--osm', default=False, action='store_true', help='provide view in OSM format') |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 765 | |
| 766 | # view network |
| 767 | view_network = view_sub_subparsers.add_parser('network') |
| 768 | view_network.add_argument('network_name', action='store', |
| 769 | help='- view network for specific network name in vcloud director') |
| 770 | view_network.add_argument('-u', '--uuid', default=False, action='store_true', help='view network based on uuid') |
| 771 | |
| 772 | # view VDC command and actions |
| 773 | view_vdc = view_sub_subparsers.add_parser('vdc') |
| 774 | view_vdc.add_argument('vdc_name', action='store', |
| 775 | help='- View VDC based and action based on provided vdc uuid') |
| 776 | view_vdc.add_argument('-u', '--uuid', default=False, action='store_true', help='view vdc based on uuid') |
| 777 | |
| 778 | # view organization command and actions |
| 779 | view_org = view_sub_subparsers.add_parser('org') |
| 780 | view_org.add_argument('org_name', action='store', |
| 781 | help='- View VDC based and action based on provided vdc uuid') |
| 782 | view_org.add_argument('-u', '--uuid', default=False, action='store_true', help='view org based on uuid') |
| 783 | |
| bayramov | b6ffe79 | 2016-09-28 11:50:56 +0400 | [diff] [blame] | 784 | # upload image action |
| 785 | image_sub = parser_subparsers.add_parser('image') |
| 786 | image_subparsers = image_sub.add_subparsers(dest='action') |
| 787 | upload_parser = image_subparsers.add_parser('upload') |
| 788 | upload_parser.add_argument('image', default=False, action='store', help='- valid path to OVF image ') |
| 789 | upload_parser.add_argument('catalog', default=False, action='store_true', help='- catalog name') |
| 790 | |
| 791 | # boot vm action |
| 792 | boot_parser = image_subparsers.add_parser('boot') |
| 793 | boot_parser.add_argument('image', default=False, action='store', help='- Image name') |
| 794 | boot_parser.add_argument('vmname', default=False, action='store', help='- VM name') |
| 795 | boot_parser.add_argument('-u', '--uuid', default=False, action='store_true', help='view org based on uuid') |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 796 | |
| 797 | namespace = parser.parse_args() |
| 798 | # put command_line args to mapping |
| 799 | command_line_args = {k: v for k, v in vars(namespace).items() if v} |
| 800 | |
| 801 | d = defaults.copy() |
| 802 | d.update(os.environ) |
| 803 | d.update(command_line_args) |
| 804 | |
| 805 | logger = logging.getLogger('mano.vim.vmware') |
| 806 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
| 807 | ch = logging.StreamHandler() |
| 808 | ch.setLevel(str.upper(d['debug'])) |
| 809 | ch.setFormatter(formatter) |
| 810 | logger.addHandler(ch) |
| 811 | logger.setLevel(getattr(logging, str.upper(d['debug']))) |
| 812 | logger.info( |
| 813 | "Connecting {} username: {} org: {} vdc: {} ".format(d['vcdhost'], d['vcduser'], d['vcdorg'], d['vcdvdc'])) |
| 814 | |
| 815 | logger.debug("command: \"{}\" actio: \"{}\"".format(d['command'], d['action'])) |
| bayramov | a09cf38 | 2016-09-28 04:13:46 +0400 | [diff] [blame] | 816 | |
| 817 | # main entry point. |
| bayramov | 6c0e3d4 | 2016-09-27 03:03:32 -0700 | [diff] [blame] | 818 | vmwarecli(namespace=namespace) |