a5e400e46262e9baf4fa295e73f6d0faffa456f6
1 # -*- coding: utf-8 -*-
3 # This file is standalone vmware vcloud director util
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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
18 # For those usages not covered by the Apache License, Version 2.0 please
19 # contact with: mbayramov@vmware.com
24 Provide standalone application to work with vCloud director rest api.
35 from xml
.etree
import ElementTree
as ET
37 from pyvcloud
import Http
38 from pyvcloud
.vcloudair
import VCA
39 from pyvcloud
.schema
.vcd
.v1_5
.schemas
.vcloud
.networkType
import *
40 from pyvcloud
.schema
.vcd
.v1_5
.schemas
.vcloud
import sessionType
, organizationType
, \
41 vAppType
, organizationListType
, vdcType
, catalogType
, queryRecordViewType
, \
42 networkType
, vcloudType
, taskType
, diskType
, vmsType
, vdcTemplateListType
, mediaType
43 from xml
.sax
.saxutils
import escape
54 from vimconn_vmware
import vimconnector
55 from requests
.packages
.urllib3
.exceptions
import InsecureRequestWarning
56 from prettytable
import PrettyTable
57 from xml
.etree
import ElementTree
as XmlElementTree
58 from prettytable
import PrettyTable
60 requests
.packages
.urllib3
.disable_warnings(InsecureRequestWarning
)
62 __author__
= "Mustafa Bayramov"
63 __date__
= "$16-Sep-2016 11:09:29$"
66 def delete_network_action(vca
=None, network_uuid
=None):
68 Method leverages vCloud director and query network based on network uuid
71 vca - is active VCA connection.
72 network_uuid - is a network uuid
75 The return XML respond
78 if vca
is None or network_uuid
is None:
81 url_list
= [vca
.host
, '/api/admin/network/', network_uuid
]
82 vm_list_rest_call
= ''.join(url_list
)
84 if not (not vca
.vcloud_session
or not vca
.vcloud_session
.organization
):
85 response
= Http
.get(url
=vm_list_rest_call
,
86 headers
=vca
.vcloud_session
.get_vcloud_headers(),
89 if response
.status_code
== requests
.codes
.ok
:
90 print response
.content
91 return response
.content
96 def print_vapp(vapp_dict
=None):
97 """ Method takes vapp_dict and print in tabular format
100 vapp_dict: container vapp object.
106 # following key available to print
108 # {'status': 'POWERED_OFF', 'storageProfileName': '*', 'hardwareVersion': '7', 'vmToolsVersion': '0',
110 # 'href': 'https://172.16.254.206/api/vAppTemplate/vm-129e22e8-08dc-4cb6-8358-25f635e65d3b',
111 # 'isBusy': 'false', 'isDeployed': 'false', 'isInMaintenanceMode': 'false', 'isVAppTemplate': 'true',
112 # 'networkName': 'nat', 'isDeleted': 'false', 'catalogName': 'Cirros',
113 # 'containerName': 'Cirros Template', # 'container': 'https://172.16.254.206/api/vAppTemplate/vappTemplate-b966453d-c361-4505-9e38-ccef45815e5d',
114 # 'name': 'Cirros', 'pvdcHighestSupportedHardwareVersion': '11', 'isPublished': 'false',
115 # 'numberOfCpus': '1', 'vdc': 'https://172.16.254.206/api/vdc/a5056f85-418c-4bfd-8041-adb0f48be9d9',
116 # 'guestOs': 'Other (32-bit)', 'isVdcEnabled': 'true'}
118 if vapp_dict
is None:
121 vm_table
= PrettyTable(['vapp uuid',
126 'storageProfileName',
127 'vcpu', 'memory', 'hw ver'])
132 entry
.append(vapp_dict
[k
]['containerName'])
133 entry
.append(vapp_dict
[k
]['vdc'].split('/')[-1:][0])
134 entry
.append(vapp_dict
[k
]['networkName'])
135 entry
.append(vapp_dict
[k
]['catalogName'])
136 entry
.append(vapp_dict
[k
]['storageProfileName'])
137 entry
.append(vapp_dict
[k
]['numberOfCpus'])
138 entry
.append(vapp_dict
[k
]['memoryMB'])
139 entry
.append(vapp_dict
[k
]['pvdcHighestSupportedHardwareVersion'])
141 vm_table
.add_row(entry
)
146 def print_org(org_dict
=None):
147 """ Method takes vapp_dict and print in tabular format
150 org_dict: dictionary of organization where key is org uuid.
159 org_table
= PrettyTable(['org uuid', 'name'])
161 entry
= [k
, org_dict
[k
]]
162 org_table
.add_row(entry
)
167 def print_vm_list(vm_dict
=None):
168 """ Method takes vapp_dict and print in tabular format
171 org_dict: dictionary of organization where key is org uuid.
179 vm_table
= PrettyTable(
180 ['vm uuid', 'vm name', 'vapp uuid', 'vdc uuid', 'network name', 'is deployed', 'vcpu', 'memory', 'status'])
186 entry
.append(vm_dict
[k
]['name'])
187 entry
.append(vm_dict
[k
]['container'].split('/')[-1:][0][5:])
188 entry
.append(vm_dict
[k
]['vdc'].split('/')[-1:][0])
189 entry
.append(vm_dict
[k
]['networkName'])
190 entry
.append(vm_dict
[k
]['isDeployed'])
191 entry
.append(vm_dict
[k
]['numberOfCpus'])
192 entry
.append(vm_dict
[k
]['memoryMB'])
193 entry
.append(vm_dict
[k
]['status'])
194 vm_table
.add_row(entry
)
197 logger
.error("wrong key {}".format(KeyError.message
))
201 def print_org_details(org_dict
=None):
202 """ Method takes vapp_dict and print in tabular format
205 org_dict: dictionary of organization where key is org uuid.
217 if org_dict
.has_key('networks'):
218 network_dict
= org_dict
['networks']
220 if org_dict
.has_key('vdcs'):
221 vdcs_dict
= org_dict
['vdcs']
223 if org_dict
.has_key('catalogs'):
224 catalogs_dict
= org_dict
['catalogs']
226 vdc_table
= PrettyTable(['vdc uuid', 'vdc name'])
228 entry
= [k
, vdcs_dict
[k
]]
229 vdc_table
.add_row(entry
)
231 network_table
= PrettyTable(['network uuid', 'network name'])
232 for k
in network_dict
:
233 entry
= [k
, network_dict
[k
]]
234 network_table
.add_row(entry
)
236 catalog_table
= PrettyTable(['catalog uuid', 'catalog name'])
237 for k
in catalogs_dict
:
238 entry
= [k
, catalogs_dict
[k
]]
239 catalog_table
.add_row(entry
)
246 logger
.error("wrong key {}".format(KeyError.message
))
247 logger
.logger
.debug(traceback
.format_exc())
250 def delete_actions(vim
=None, action
=None, namespace
=None):
251 if action
== 'network' or namespace
.action
== 'network':
252 logger
.debug("Requesting delete for network {}".format(namespace
.network_name
))
253 network_uuid
= namespace
.network_name
254 # if request name based we need find UUID
255 # TODO optimize it or move to external function
256 if not namespace
.uuid
:
257 org_dict
= vim
.get_org_list()
259 org_net
= vim
.get_org(org
)['networks']
260 for network
in org_net
:
261 if org_net
[network
] == namespace
.network_name
:
262 network_uuid
= network
264 vim
.delete_network_action(network_uuid
=network_uuid
)
267 def list_actions(vim
=None, action
=None, namespace
=None):
268 if action
== 'vms' or namespace
.action
== 'vms':
269 vm_dict
= vim
.get_vm_list(vdc_name
=namespace
.vcdvdc
)
270 print_vm_list(vm_dict
=vm_dict
)
271 elif action
== 'vapps' or namespace
.action
== 'vapps':
272 vapp_dict
= vim
.get_vapp_list(vdc_name
=namespace
.vcdvdc
)
273 print_vapp(vapp_dict
=vapp_dict
)
274 elif action
== 'networks' or namespace
.action
== 'networks':
275 print "Requesting networks"
276 # var = OrgVdcNetworkType.get_status()
277 elif action
== 'vdc' or namespace
.action
== 'vdc':
278 vm_dict
= vim
.get_vm_list(vdc_name
=namespace
.vcdvdc
)
279 print_vm_list(vm_dict
=vm_dict
)
280 elif action
== 'org' or namespace
.action
== 'org':
281 logger
.debug("Listing avaliable orgs")
282 print_org(org_dict
=vim
.get_org_list())
287 def view_actions(vim
=None, action
=None, namespace
=None):
289 if action
== 'org' or namespace
.action
== 'org':
291 orgs
= vim
.get_org_list()
293 if namespace
.org_name
in orgs
:
294 org_id
= namespace
.org_name
296 # we need find UUID based on name provided
298 if orgs
[org
] == namespace
.org_name
:
302 logger
.debug("Requesting view for orgs {}".format(org_id
))
303 print_org_details(vim
.get_org(org_uuid
=org_id
))
306 if action
== 'vapp' or namespace
.action
== 'vapp':
307 if namespace
.vapp_name
is not None and namespace
.uuid
== False:
308 logger
.debug("Requesting vapp {} for vdc {}".format(namespace
.vapp_name
, namespace
.vcdvdc
))
311 # if request based on just name we need get UUID
312 if not namespace
.uuid
:
313 vappid
= vim
.get_vappid(vdc
=namespace
.vcdvdc
, vapp_name
=namespace
.vapp_name
)
315 vapp_dict
= vim
.get_vapp(vdc_name
=namespace
.vcdvdc
, vapp_name
=vappid
, isuuid
=True)
316 print_vapp(vapp_dict
=vapp_dict
)
319 if action
== 'network' or namespace
.action
== 'network':
320 logger
.debug("Requesting view for network {}".format(namespace
.network_name
))
321 network_uuid
= namespace
.network_name
322 # if request name based we need find UUID
323 # TODO optimize it or move to external function
324 if not namespace
.uuid
:
325 org_dict
= vim
.get_org_list()
327 org_net
= vim
.get_org(org
)['networks']
328 for network
in org_net
:
329 if org_net
[network
] == namespace
.network_name
:
330 network_uuid
= network
332 print vim
.get_vcd_network(network_uuid
=network_uuid
)
335 def create_actions(vim
=None, action
=None, namespace
=None):
336 """Method gets provider vdc view from vcloud director
339 vim - is Cloud director vim connector
340 action - action for create ( network / vdc etc)
343 The return xml content of respond or None
345 if action
== 'network' or namespace
.action
== 'network':
346 logger
.debug("Creating a network in vcloud director".format(namespace
.network_name
))
347 network_uuid
= vim
.create_network(namespace
.network_name
)
348 if network_uuid
is not None:
349 print ("Crated new network {} and uuid: {}".format(namespace
.network_name
, network_uuid
))
351 print ("Failed create a new network {}".format(namespace
.network_name
))
352 elif action
== 'vdc' or namespace
.action
== 'vdc':
353 logger
.debug("Creating a new vdc in vcloud director.".format(namespace
.vdc_name
))
354 vdc_uuid
= vim
.create_vdc(namespace
.vdc_name
)
355 if vdc_uuid
is not None:
356 print ("Crated new vdc {} and uuid: {}".format(namespace
.vdc_name
, vdc_uuid
))
358 print ("Failed create a new vdc {}".format(namespace
.vdc_name
))
363 def vmwarecli(command
=None, action
=None, namespace
=None):
366 urllib3
.disable_warnings()
367 vim
= vimconnector('0cd19677-7517-11e6-aa08-000c29db3077',
369 'a5056f85-418c-4bfd-8041-adb0f48be9d9',
371 'https://172.16.254.206',
372 'https://172.16.254.206',
375 "DEBUG", config
={'admin_username': 'Administrator', 'admin_password': 'qwerty123'})
377 vim
.vca
= vim
.connect()
379 # "{'status': 'ACTIVE'}
380 # 2016-09-26 13:06:33,989 - mano.vim.vmware - DEBUG - Adding 4d2e9ec6-e3d8-4014-a1ab-8b622524bd9c to a list vcd id a5056f85-418c-4bfd-8041-adb0f48be9d9 network tefexternal
381 # Dict contains {'status': 'ACTIVE'}
382 # 2016-09-26 13:06:33,989 - mano.vim.vmware - DEBUG - Adding 93729eaa-4159-4d18-ac28-b000f91bd331 to a list vcd id a5056f85-418c-4bfd-8041-adb0f48be9d9 network default
383 # Dict contains {'status': 'ACTIVE'}
385 vim
.get_network_list(filter_dict
={'status': 'ACTIVE', 'type': 'bridge'})
386 # vim.get_network_list(filter_dict={'status' : 'ACTIVE'})
388 # print vim.get_vminstance('7e06889a-50c4-4b08-8877-c1ef001eb030')
389 # vim.get_network_name_by_id()
392 # get_network_action(vca=vca, network_uuid="123")
395 if command
== 'list' or namespace
.command
== 'list':
396 logger
.debug("Client requested list action")
397 # route request to list actions
398 list_actions(vim
=vim
, action
=action
, namespace
=namespace
)
401 if command
== 'view' or namespace
.command
== 'view':
402 logger
.debug("Client requested view action")
403 view_actions(vim
=vim
, action
=action
, namespace
=namespace
)
406 if command
== 'delete' or namespace
.command
== 'delete':
407 logger
.debug("Client requested delete action")
408 delete_actions(vim
=vim
, action
=action
, namespace
=namespace
)
411 if command
== 'create' or namespace
.command
== 'create':
412 logger
.debug("Client requested create action")
413 create_actions(vim
=vim
, action
=action
, namespace
=namespace
)
416 # def get_vappid(vdc, vapp_name):
417 # refs = filter(lambda ref: ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',vdc.ResourceEntities.ResourceEntity)
419 # return refs[0].href.split("vapp")[1][1:]
422 if __name__
== '__main__':
423 defaults
= {'vcdvdc': 'default',
425 'vcdpassword': 'admin',
426 'vcdhost': 'https://localhost',
430 parser
= argparse
.ArgumentParser()
431 parser
.add_argument('-u', '--vcduser', help='vcloud director username', type=str)
432 parser
.add_argument('-p', '--vcdpassword', help='vcloud director password', type=str)
433 parser
.add_argument('-c', '--vcdhost', help='vcloud director host', type=str)
434 parser
.add_argument('-o', '--vcdorg', help='vcloud director org', type=str)
435 parser
.add_argument('-v', '--vcdvdc', help='vcloud director vdc', type=str)
436 parser
.add_argument('-d', '--debug', help='debug level', type=int)
438 parser_subparsers
= parser
.add_subparsers(help='commands', dest
='command')
439 sub
= parser_subparsers
.add_parser('list', help='List objects (VMs, vApps, networks)')
440 sub_subparsers
= sub
.add_subparsers(dest
='action')
441 view_vms
= sub_subparsers
.add_parser('vms', help='list - all vm deployed in vCloud director')
442 view_vapps
= sub_subparsers
.add_parser('vapps', help='list - all vapps deployed in vCloud director')
443 view_network
= sub_subparsers
.add_parser('networks', help='list - all networks deployed')
444 view_vdc
= sub_subparsers
.add_parser('vdc', help='list - list all vdc for organization accessible to you')
445 view_vdc
= sub_subparsers
.add_parser('org', help='list - list of organizations accessible to you.')
447 create_sub
= parser_subparsers
.add_parser('create')
448 create_sub_subparsers
= create_sub
.add_subparsers(dest
='action')
449 create_vms
= create_sub_subparsers
.add_parser('vms')
450 create_vapp
= create_sub_subparsers
.add_parser('vapp')
451 create_vapp
.add_argument('uuid')
454 create_network
= create_sub_subparsers
.add_parser('network')
455 create_network
.add_argument('network_name', action
='store', help='create a network for a vdc')
458 create_vdc
= create_sub_subparsers
.add_parser('vdc')
459 create_vdc
.add_argument('vdc_name', action
='store', help='create a new VDC for org')
461 delete_sub
= parser_subparsers
.add_parser('delete')
462 del_sub_subparsers
= delete_sub
.add_subparsers(dest
='action')
463 del_vms
= del_sub_subparsers
.add_parser('vms')
464 del_vapp
= del_sub_subparsers
.add_parser('vapp')
465 del_vapp
.add_argument('uuid', help='view vapp based on UUID')
468 del_network
= del_sub_subparsers
.add_parser('network')
469 del_network
.add_argument('network_name', action
='store',
470 help='- delete network for vcloud director by provided name')
471 del_network
.add_argument('-u', '--uuid', default
=False, action
='store_true',
472 help='delete network for vcloud director by provided uuid')
475 del_vdc
= del_sub_subparsers
.add_parser('vdc')
477 view_sub
= parser_subparsers
.add_parser('view')
478 view_sub_subparsers
= view_sub
.add_subparsers(dest
='action')
480 view_vms_parser
= view_sub_subparsers
.add_parser('vms')
481 view_vms_parser
.add_argument('uuid', default
=False, action
='store_true',
482 help='- View VM for specific uuid in vcloud director')
483 view_vms_parser
.add_argument('name', default
=False, action
='store_true',
484 help='- View VM for specific vapp name in vcloud director')
487 view_vapp_parser
= view_sub_subparsers
.add_parser('vapp')
488 view_vapp_parser
.add_argument('vapp_name', action
='store',
489 help='- view vapp for specific vapp name in vcloud director')
490 view_vapp_parser
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view vapp based on uuid')
493 view_network
= view_sub_subparsers
.add_parser('network')
494 view_network
.add_argument('network_name', action
='store',
495 help='- view network for specific network name in vcloud director')
496 view_network
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view network based on uuid')
498 # view VDC command and actions
499 view_vdc
= view_sub_subparsers
.add_parser('vdc')
500 view_vdc
.add_argument('vdc_name', action
='store',
501 help='- View VDC based and action based on provided vdc uuid')
502 view_vdc
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view vdc based on uuid')
504 # view organization command and actions
505 view_org
= view_sub_subparsers
.add_parser('org')
506 view_org
.add_argument('org_name', action
='store',
507 help='- View VDC based and action based on provided vdc uuid')
508 view_org
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view org based on uuid')
511 # view_org.add_argument('uuid', default=False, action='store',
512 # help='- View Organization and action based on provided uuid.')
513 # view_org.add_argument('name', default=False, action='store_true',
514 # help='- View Organization and action based on provided name')
516 namespace
= parser
.parse_args()
517 # put command_line args to mapping
518 command_line_args
= {k
: v
for k
, v
in vars(namespace
).items() if v
}
522 d
.update(command_line_args
)
524 logger
= logging
.getLogger('mano.vim.vmware')
525 formatter
= logging
.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
526 ch
= logging
.StreamHandler()
527 ch
.setLevel(str.upper(d
['debug']))
528 ch
.setFormatter(formatter
)
529 logger
.addHandler(ch
)
530 logger
.setLevel(getattr(logging
, str.upper(d
['debug'])))
532 "Connecting {} username: {} org: {} vdc: {} ".format(d
['vcdhost'], d
['vcduser'], d
['vcdorg'], d
['vcdvdc']))
534 logger
.debug("command: \"{}\" actio: \"{}\"".format(d
['command'], d
['action']))
535 vmwarecli(namespace
=namespace
)