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 #TODO move to main vim
67 def delete_network_action(vca
=None, network_uuid
=None):
69 Method leverages vCloud director and query network based on network uuid
72 vca - is active VCA connection.
73 network_uuid - is a network uuid
76 The return XML respond
79 if vca
is None or network_uuid
is None:
82 url_list
= [vca
.host
, '/api/admin/network/', network_uuid
]
83 vm_list_rest_call
= ''.join(url_list
)
85 if not (not vca
.vcloud_session
or not vca
.vcloud_session
.organization
):
86 response
= Http
.get(url
=vm_list_rest_call
,
87 headers
=vca
.vcloud_session
.get_vcloud_headers(),
90 if response
.status_code
== requests
.codes
.ok
:
91 print response
.content
92 return response
.content
97 def print_vapp(vapp_dict
=None):
98 """ Method takes vapp_dict and print in tabular format
101 vapp_dict: container vapp object.
107 # 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'])
131 entry
.append(vapp_dict
[k
]['containerName'])
132 entry
.append(vapp_dict
[k
]['vdc'].split('/')[-1:][0])
133 entry
.append(vapp_dict
[k
]['networkName'])
134 entry
.append(vapp_dict
[k
]['catalogName'])
135 entry
.append(vapp_dict
[k
]['storageProfileName'])
136 entry
.append(vapp_dict
[k
]['numberOfCpus'])
137 entry
.append(vapp_dict
[k
]['memoryMB'])
138 entry
.append(vapp_dict
[k
]['pvdcHighestSupportedHardwareVersion'])
140 vm_table
.add_row(entry
)
145 def print_org(org_dict
=None):
146 """ Method takes vapp_dict and print in tabular format
149 org_dict: dictionary of organization where key is org uuid.
158 org_table
= PrettyTable(['org uuid', 'name'])
160 entry
= [k
, org_dict
[k
]]
161 org_table
.add_row(entry
)
166 def print_vm_list(vm_dict
=None):
167 """ Method takes vapp_dict and print in tabular format
170 org_dict: dictionary of organization where key is org uuid.
178 vm_table
= PrettyTable(
179 ['vm uuid', 'vm name', 'vapp uuid', 'vdc uuid', 'network name', 'is deployed', 'vcpu', 'memory', 'status'])
185 entry
.append(vm_dict
[k
]['name'])
186 entry
.append(vm_dict
[k
]['container'].split('/')[-1:][0][5:])
187 entry
.append(vm_dict
[k
]['vdc'].split('/')[-1:][0])
188 entry
.append(vm_dict
[k
]['networkName'])
189 entry
.append(vm_dict
[k
]['isDeployed'])
190 entry
.append(vm_dict
[k
]['numberOfCpus'])
191 entry
.append(vm_dict
[k
]['memoryMB'])
192 entry
.append(vm_dict
[k
]['status'])
193 vm_table
.add_row(entry
)
196 logger
.error("wrong key {}".format(KeyError.message
))
200 def print_org_details(org_dict
=None):
201 """ Method takes vapp_dict and print in tabular format
204 org_dict: dictionary of organization where key is org uuid.
216 if org_dict
.has_key('networks'):
217 network_dict
= org_dict
['networks']
219 if org_dict
.has_key('vdcs'):
220 vdcs_dict
= org_dict
['vdcs']
222 if org_dict
.has_key('catalogs'):
223 catalogs_dict
= org_dict
['catalogs']
225 vdc_table
= PrettyTable(['vdc uuid', 'vdc name'])
227 entry
= [k
, vdcs_dict
[k
]]
228 vdc_table
.add_row(entry
)
230 network_table
= PrettyTable(['network uuid', 'network name'])
231 for k
in network_dict
:
232 entry
= [k
, network_dict
[k
]]
233 network_table
.add_row(entry
)
235 catalog_table
= PrettyTable(['catalog uuid', 'catalog name'])
236 for k
in catalogs_dict
:
237 entry
= [k
, catalogs_dict
[k
]]
238 catalog_table
.add_row(entry
)
245 logger
.error("wrong key {}".format(KeyError.message
))
246 logger
.logger
.debug(traceback
.format_exc())
249 def delete_actions(vim
=None, action
=None, namespace
=None):
250 if action
== 'network' or namespace
.action
== 'network':
251 logger
.debug("Requesting delete for network {}".format(namespace
.network_name
))
252 network_uuid
= namespace
.network_name
253 # if request name based we need find UUID
254 # TODO optimize it or move to external function
255 if not namespace
.uuid
:
256 org_dict
= vim
.get_org_list()
258 org_net
= vim
.get_org(org
)['networks']
259 for network
in org_net
:
260 if org_net
[network
] == namespace
.network_name
:
261 network_uuid
= network
263 vim
.delete_network_action(network_uuid
=network_uuid
)
266 def list_actions(vim
=None, action
=None, namespace
=None):
267 if action
== 'vms' or namespace
.action
== 'vms':
268 vm_dict
= vim
.get_vm_list(vdc_name
=namespace
.vcdvdc
)
269 print_vm_list(vm_dict
=vm_dict
)
270 elif action
== 'vapps' or namespace
.action
== 'vapps':
271 vapp_dict
= vim
.get_vapp_list(vdc_name
=namespace
.vcdvdc
)
272 print_vapp(vapp_dict
=vapp_dict
)
273 elif action
== 'networks' or namespace
.action
== 'networks':
274 print "Requesting networks"
275 # var = OrgVdcNetworkType.get_status()
276 elif action
== 'vdc' or namespace
.action
== 'vdc':
277 vm_dict
= vim
.get_vm_list(vdc_name
=namespace
.vcdvdc
)
278 print_vm_list(vm_dict
=vm_dict
)
279 elif action
== 'org' or namespace
.action
== 'org':
280 logger
.debug("Listing avaliable orgs")
281 print_org(org_dict
=vim
.get_org_list())
286 def view_actions(vim
=None, action
=None, namespace
=None):
288 if action
== 'org' or namespace
.action
== 'org':
290 orgs
= vim
.get_org_list()
292 if namespace
.org_name
in orgs
:
293 org_id
= namespace
.org_name
295 # we need find UUID based on name provided
297 if orgs
[org
] == namespace
.org_name
:
301 logger
.debug("Requesting view for orgs {}".format(org_id
))
302 print_org_details(vim
.get_org(org_uuid
=org_id
))
305 if action
== 'vapp' or namespace
.action
== 'vapp':
306 if namespace
.vapp_name
is not None and namespace
.uuid
== False:
307 logger
.debug("Requesting vapp {} for vdc {}".format(namespace
.vapp_name
, namespace
.vcdvdc
))
310 # if request based on just name we need get UUID
311 if not namespace
.uuid
:
312 vappid
= vim
.get_vappid(vdc
=namespace
.vcdvdc
, vapp_name
=namespace
.vapp_name
)
314 vapp_dict
= vim
.get_vapp(vdc_name
=namespace
.vcdvdc
, vapp_name
=vappid
, isuuid
=True)
315 print_vapp(vapp_dict
=vapp_dict
)
318 if action
== 'network' or namespace
.action
== 'network':
319 logger
.debug("Requesting view for network {}".format(namespace
.network_name
))
320 network_uuid
= namespace
.network_name
321 # if request name based we need find UUID
322 # TODO optimize it or move to external function
323 if not namespace
.uuid
:
324 org_dict
= vim
.get_org_list()
326 org_net
= vim
.get_org(org
)['networks']
327 for network
in org_net
:
328 if org_net
[network
] == namespace
.network_name
:
329 network_uuid
= network
331 print vim
.get_vcd_network(network_uuid
=network_uuid
)
334 def create_actions(vim
=None, action
=None, namespace
=None):
335 """Method gets provider vdc view from vcloud director
338 vim - is Cloud director vim connector
339 action - action for create ( network / vdc etc)
342 The return xml content of respond or None
344 if action
== 'network' or namespace
.action
== 'network':
345 logger
.debug("Creating a network in vcloud director".format(namespace
.network_name
))
346 network_uuid
= vim
.create_network(namespace
.network_name
)
347 if network_uuid
is not None:
348 print ("Crated new network {} and uuid: {}".format(namespace
.network_name
, network_uuid
))
350 print ("Failed create a new network {}".format(namespace
.network_name
))
351 elif action
== 'vdc' or namespace
.action
== 'vdc':
352 logger
.debug("Creating a new vdc in vcloud director.".format(namespace
.vdc_name
))
353 vdc_uuid
= vim
.create_vdc(namespace
.vdc_name
)
354 if vdc_uuid
is not None:
355 print ("Crated new vdc {} and uuid: {}".format(namespace
.vdc_name
, vdc_uuid
))
357 print ("Failed create a new vdc {}".format(namespace
.vdc_name
))
362 def vmwarecli(command
=None, action
=None, namespace
=None):
364 logger
.debug("Namespace {}".format(namespace
))
365 urllib3
.disable_warnings()
367 if namespace
.vcdpassword
is None:
368 vcdpasword
= input("vcd password ")
370 vcdpasword
= namespace
.vcdpassword
371 vim
= vimconnector(uuid
=None,
372 name
=namespace
.org_name
,
374 tenant_name
=namespace
.vcdvdc
,
375 url
=namespace
.vcdhost
,
376 url_admin
=namespace
.vcdhost
,
377 user
=namespace
.vcduser
,
378 passwd
=namespace
.vcdpassword
,
380 config
={'admin_username': namespace
.vcdamdin
, 'admin_password': namespace
.vcdadminpassword
})
381 vim
.vca
= vim
.connect()
384 if command
== 'list' or namespace
.command
== 'list':
385 logger
.debug("Client requested list action")
386 # route request to list actions
387 list_actions(vim
=vim
, action
=action
, namespace
=namespace
)
390 if command
== 'view' or namespace
.command
== 'view':
391 logger
.debug("Client requested view action")
392 view_actions(vim
=vim
, action
=action
, namespace
=namespace
)
395 if command
== 'delete' or namespace
.command
== 'delete':
396 logger
.debug("Client requested delete action")
397 delete_actions(vim
=vim
, action
=action
, namespace
=namespace
)
400 if command
== 'create' or namespace
.command
== 'create':
401 logger
.debug("Client requested create action")
402 create_actions(vim
=vim
, action
=action
, namespace
=namespace
)
405 if __name__
== '__main__':
406 defaults
= {'vcdvdc': 'default',
408 'vcdpassword': 'admin',
409 'vcdhost': 'https://localhost',
413 parser
= argparse
.ArgumentParser()
414 parser
.add_argument('-u', '--vcduser', help='vcloud director username', type=str)
415 parser
.add_argument('-p', '--vcdpassword', help='vcloud director password', type=str)
416 parser
.add_argument('-U', '--vcdamdin', help='vcloud director password', type=str)
417 parser
.add_argument('-P', '--vcdadminpassword', help='vcloud director password', type=str)
418 parser
.add_argument('-c', '--vcdhost', help='vcloud director host', type=str)
419 parser
.add_argument('-o', '--vcdorg', help='vcloud director org', type=str)
420 parser
.add_argument('-v', '--vcdvdc', help='vcloud director vdc', type=str)
421 parser
.add_argument('-d', '--debug', help='debug level', type=int)
423 parser_subparsers
= parser
.add_subparsers(help='commands', dest
='command')
424 sub
= parser_subparsers
.add_parser('list', help='List objects (VMs, vApps, networks)')
425 sub_subparsers
= sub
.add_subparsers(dest
='action')
426 view_vms
= sub_subparsers
.add_parser('vms', help='list - all vm deployed in vCloud director')
427 view_vapps
= sub_subparsers
.add_parser('vapps', help='list - all vapps deployed in vCloud director')
428 view_network
= sub_subparsers
.add_parser('networks', help='list - all networks deployed')
429 view_vdc
= sub_subparsers
.add_parser('vdc', help='list - list all vdc for organization accessible to you')
430 view_vdc
= sub_subparsers
.add_parser('org', help='list - list of organizations accessible to you.')
432 create_sub
= parser_subparsers
.add_parser('create')
433 create_sub_subparsers
= create_sub
.add_subparsers(dest
='action')
434 create_vms
= create_sub_subparsers
.add_parser('vms')
435 create_vapp
= create_sub_subparsers
.add_parser('vapp')
436 create_vapp
.add_argument('uuid')
439 create_network
= create_sub_subparsers
.add_parser('network')
440 create_network
.add_argument('network_name', action
='store', help='create a network for a vdc')
443 create_vdc
= create_sub_subparsers
.add_parser('vdc')
444 create_vdc
.add_argument('vdc_name', action
='store', help='create a new VDC for org')
446 delete_sub
= parser_subparsers
.add_parser('delete')
447 del_sub_subparsers
= delete_sub
.add_subparsers(dest
='action')
448 del_vms
= del_sub_subparsers
.add_parser('vms')
449 del_vapp
= del_sub_subparsers
.add_parser('vapp')
450 del_vapp
.add_argument('uuid', help='view vapp based on UUID')
453 del_network
= del_sub_subparsers
.add_parser('network')
454 del_network
.add_argument('network_name', action
='store',
455 help='- delete network for vcloud director by provided name')
456 del_network
.add_argument('-u', '--uuid', default
=False, action
='store_true',
457 help='delete network for vcloud director by provided uuid')
460 del_vdc
= del_sub_subparsers
.add_parser('vdc')
462 view_sub
= parser_subparsers
.add_parser('view')
463 view_sub_subparsers
= view_sub
.add_subparsers(dest
='action')
465 view_vms_parser
= view_sub_subparsers
.add_parser('vms')
466 view_vms_parser
.add_argument('uuid', default
=False, action
='store_true',
467 help='- View VM for specific uuid in vcloud director')
468 view_vms_parser
.add_argument('name', default
=False, action
='store_true',
469 help='- View VM for specific vapp name in vcloud director')
472 view_vapp_parser
= view_sub_subparsers
.add_parser('vapp')
473 view_vapp_parser
.add_argument('vapp_name', action
='store',
474 help='- view vapp for specific vapp name in vcloud director')
475 view_vapp_parser
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view vapp based on uuid')
478 view_network
= view_sub_subparsers
.add_parser('network')
479 view_network
.add_argument('network_name', action
='store',
480 help='- view network for specific network name in vcloud director')
481 view_network
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view network based on uuid')
483 # view VDC command and actions
484 view_vdc
= view_sub_subparsers
.add_parser('vdc')
485 view_vdc
.add_argument('vdc_name', action
='store',
486 help='- View VDC based and action based on provided vdc uuid')
487 view_vdc
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view vdc based on uuid')
489 # view organization command and actions
490 view_org
= view_sub_subparsers
.add_parser('org')
491 view_org
.add_argument('org_name', action
='store',
492 help='- View VDC based and action based on provided vdc uuid')
493 view_org
.add_argument('-u', '--uuid', default
=False, action
='store_true', help='view org based on uuid')
496 # view_org.add_argument('uuid', default=False, action='store',
497 # help='- View Organization and action based on provided uuid.')
498 # view_org.add_argument('name', default=False, action='store_true',
499 # help='- View Organization and action based on provided name')
501 namespace
= parser
.parse_args()
502 # put command_line args to mapping
503 command_line_args
= {k
: v
for k
, v
in vars(namespace
).items() if v
}
507 d
.update(command_line_args
)
509 logger
= logging
.getLogger('mano.vim.vmware')
510 formatter
= logging
.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
511 ch
= logging
.StreamHandler()
512 ch
.setLevel(str.upper(d
['debug']))
513 ch
.setFormatter(formatter
)
514 logger
.addHandler(ch
)
515 logger
.setLevel(getattr(logging
, str.upper(d
['debug'])))
517 "Connecting {} username: {} org: {} vdc: {} ".format(d
['vcdhost'], d
['vcduser'], d
['vcdorg'], d
['vcdvdc']))
519 logger
.debug("command: \"{}\" actio: \"{}\"".format(d
['command'], d
['action']))
522 vmwarecli(namespace
=namespace
)