def main(argv=None): '''Command line options.''' if argv is None: argv = sys.argv else: sys.argv.extend(argv) program_name = os.path.basename(sys.argv[0]) program_version = "v%s" % __version__ program_build_date = str(__updated__) program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date) program_shortdesc = __import__('__main__').__doc__.split("\n")[1] program_license = '''%s Created by Jürgen Buchhammer on %s. Copyright 2016 IONOS. All rights reserved. Licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 Distributed on an "AS IS" basis without warranties or conditions of any kind, either express or implied. USAGE ''' % (program_shortdesc, str(__date__)) try: # Setup argument parser parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-u', '--user', dest='user', help='the login name') parser.add_argument('-p', '--password', dest='password', help='the login password') parser.add_argument('-L', '--Login', dest='loginfile', default=None, help='the login file to use') parser.add_argument('-t', '--type', dest='metatype', default="OVF", help='type of VM meta data') parser.add_argument('-m', '--metadata', dest='metafile', required=True, default=None, help='meta data file') parser.add_argument('-d', '--datacenterid', dest='datacenterid', default=None, help='datacenter of the new server') parser.add_argument('-D', '--DCname', dest='dcname', default=None, help='new datacenter name') parser.add_argument('-l', '--location', dest='location', default=None, help='location for new datacenter') parser.add_argument('-v', '--verbose', dest="verbose", action="count", default=0, help="set verbosity level [default: %(default)s]") parser.add_argument('-V', '--version', action='version', version=program_version_message) # Process arguments args = parser.parse_args() global verbose verbose = args.verbose if verbose > 0: print("Verbose mode on") print("start {} with args {}".format(program_name, str(args))) (user, password) = getLogin(args.loginfile, args.user, args.password) if user is None or password is None: raise ValueError("user or password resolved to None") pbclient = IonosEnterpriseService(user, password) if args.metatype == 'OVF': metadata = OFVData(args.metafile) metadata.parse() else: sys.stderr.write("Metadata type '{}' is not supported".format( args.metatype)) return 1 # we need the DC first to have the location defined dc_id = None if args.datacenterid is None: if args.dcname is None or args.location is None: sys.stderr.write( "Either '-d <id>' or '-D <name> -l <loc>' must be specified" ) return 1 # else: we will create the DC later after parsing the meta data else: dc_id = args.datacenterid if dc_id is None: location = args.location dc = Datacenter(name=args.dcname, location=location, description="created by pb_importVM") print("create new DC {}".format(str(dc))) response = pbclient.create_datacenter(dc) dc_id = response['id'] result = wait_for_request(pbclient, response['requestId']) print("wait loop returned {}".format(result)) else: dc = pbclient.get_datacenter(dc_id) location = dc['properties']['location'] print("use existing DC {} in location {}".format( dc['properties']['name'], location)) # check if images exist for disk in metadata.disks: disk_name = disk['file'] images = get_disk_image_by_name(pbclient, location, disk_name) if not images: raise ValueError( "No HDD image with name '{}' found in location {}".format( disk_name, location)) if len(images) > 1: raise ValueError( "Ambigous image name '{}' in location {}".format( disk_name, location)) disk['image'] = images[0]['id'] # now we're ready to create the VM # Server server = Server(name=metadata.name, cores=metadata.cpus, ram=metadata.ram) print("create server {}".format(str(Server))) response = pbclient.create_server(dc_id, server) srv_id = response['id'] result = wait_for_request(pbclient, response['requestId']) print("wait loop returned {}".format(str(result))) # NICs (note that createing LANs may be implicit) for nic in metadata.nics: dcnic = NIC(name=nic['nic'], lan=nic['lanid']) print("create NIC {}".format(str(dcnic))) response = pbclient.create_nic(dc_id, srv_id, dcnic) nic_id = response['id'] result = wait_for_request(pbclient, response['requestId']) print("wait loop returned {}".format(str(result))) response = pbclient.get_nic(dc_id, srv_id, nic_id, 2) mac = response['properties']['mac'] print("dcnic has MAC {} for {}".format(mac, nic_id)) # end for(nics) # Volumes (we use the image name as volume name too requests = [] for disk in metadata.disks: dcvol = Volume(name=disk['file'], size=disk['capacity'], image=disk['image'], licence_type=metadata.licenseType) print("create Volume {}".format(str(dcvol))) response = pbclient.create_volume(dc_id, dcvol) requests.append(response['requestId']) disk['volume_id'] = response['id'] # end for(disks) if requests: result = wait_for_requests(pbclient, requests, initial_wait=10, scaleup=15) print("wait loop returned {}".format(str(result))) for disk in metadata.disks: print("attach volume {}".format(disk)) response = pbclient.attach_volume(dc_id, srv_id, disk['volume_id']) result = wait_for_request(pbclient, response['requestId']) print("wait loop returned {}".format(str(result))) # end for(disks) print("import of VM succesfully finished") return 0 except KeyboardInterrupt: # handle keyboard interrupt return 0 except Exception: traceback.print_exc() sys.stderr.write("\n" + program_name + ": for help use --help\n") return 2
def main(argv=None): '''Parse command line options and dump a datacenter to snapshots and file.''' if argv is None: argv = sys.argv else: sys.argv.extend(argv) program_name = os.path.basename(sys.argv[0]) program_version = "v%s" % __version__ program_build_date = str(__updated__) program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date) program_shortdesc = __import__('__main__').__doc__.split("\n")[1] program_license = '''%s Created by J. Buchhammer on %s. Copyright 2016 IONOS. All rights reserved. Licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 Distributed on an "AS IS" basis without warranties or conditions of any kind, either express or implied. USAGE ''' % (program_shortdesc, str(__date__)) try: # Setup argument parser parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-u', '--user', dest='user', help='the login name') parser.add_argument('-p', '--password', dest='password', help='the login password') parser.add_argument('-L', '--Login', dest='loginfile', default=None, help='the login file to use') parser.add_argument('-d', '--datacenterid', dest='dc_id', required=True, default=None, help='datacenter ID of the server') parser.add_argument('-o', '--outfile', dest='outfile', default='dc-def_'+datetime.now().strftime('%Y-%m-%d_%H%M%S'), help='the output file name') parser.add_argument('-S', '--Stopalways', dest='stopalways', action='store_true', help='power off even when VM is running') parser.add_argument('-v', '--verbose', dest="verbose", action="count", default=0, help="set verbosity level [default: %(default)s]") parser.add_argument('-V', '--version', action='version', version=program_version_message) # Process arguments args = parser.parse_args() global verbose verbose = args.verbose if verbose > 0: print("Verbose mode on") print("start {} with args {}".format(program_name, str(args))) outfile = args.outfile if outfile.endswith(".json"): outfile = os.path.splitext(outfile) print("Using output file base name '{}'".format(outfile)) (user, password) = getLogin(args.loginfile, args.user, args.password) if user is None or password is None: raise ValueError("user or password resolved to None") pbclient = IonosEnterpriseService(user, password) dc_id = args.dc_id # first get all server's VM and OS state to see if we can start srv_info = getServerInfo(pbclient, dc_id) srvon = 0 for server in srv_info: if server['vmstate'] != 'SHUTOFF': print("VM {} is in state {}, but should be SHUTOFF" .format(server['name'], server['vmstate'])) srvon += 1 # end for(srv_info) if srvon > 0 and not args.stopalways: print("shutdown running OS before trying again") return 1 # now power off all VMs before starting the snapshots for server in srv_info: controlServerState(pbclient, dc_id, server['id'], action='POWEROFF') # now let's go dcdef = pbclient.get_datacenter(dc_id, 5) print("starting dump of datacenter {}".format(dcdef['properties']['name'])) dcdef_file = outfile+'_source.json' print("write source dc to {}".format(dcdef_file)) write_dc_definition(dcdef, dcdef_file) print("get existing Snapshots") # first get existing snapshots known_snapshots = dict() snapshots = pbclient.list_snapshots() for snap in snapshots['items']: print("SNAP : {}".format(json.dumps(snap))) known_snapshots[snap['properties']['name']] = snap['id'] print("create Snapshots, this may take a while ..") # we do NOT consider dangling volumes, only server-attached ones vol_snapshots = dict() # map volume id==snapshot name snapshot id for server in dcdef['entities']['servers']['items']: print("- server {}".format(server['properties']['name'])) if 'volumes' not in server['entities']: print(" server {} has no volumes" .format(server['properties']['name'])) continue # The volumes are attached by order of creation # Thus we must sort them to keep the order in the clone print("setting volume order by deviceNumber") volumes = server['entities']['volumes']['items'] new_order = sorted(volumes, key=lambda vol: vol['properties']['deviceNumber']) server['entities']['volumes']['items'] = new_order for volume in server['entities']['volumes']['items']: vol_id = volume['id'] # this will be the name too if vol_id in known_snapshots: print("use existing snapshot {} of volume {}" .format(vol_id, volume['properties']['name'])) vol_snapshots[vol_id] = known_snapshots[vol_id] else: print("taking snapshot {} of volume {}" .format(vol_id, volume['properties']['name'])) response = pbclient.create_snapshot(dc_id, vol_id, vol_id, "auto-created by pb_snapshotDatacenter") # response has no request id, need to check metadata state (BUSY, AVAILABLE..) vol_snapshots[vol_id] = response['id'] print("snapshot in progress: {}".format(str(response))) # end for(volume) # end for(server) print("Waiting for snapshots to complete") snapdone = dict() while len(snapdone) != len(vol_snapshots): sleep(10) for snap_id in vol_snapshots.values(): print("looking for {}".format(snap_id)) if snap_id in snapdone: continue snapshot = pbclient.get_snapshot(snap_id) print("snapshot {} is in state {}" .format(snap_id, snapshot['metadata']['state'])) if snapshot['metadata']['state'] == 'AVAILABLE': snapdone[snap_id] = snapshot['metadata']['state'] # end for(vol_snapshots) # end while(snapdone) # now replace the volumes image IDs print("setting snapshot id to volumes") for server in dcdef['entities']['servers']['items']: print("- server {}".format(server['properties']['name'])) if 'volumes' not in server['entities']: print(" server {} has no volumes" .format(server['properties']['name'])) continue for volume in server['entities']['volumes']['items']: vol_id = volume['id'] # this will be the name too volume['properties']['image'] = vol_snapshots[vol_id] # end for(volume) # end for(server) # As it came out, the LAN id is rearranged by order of creation # Thus we must sort the LANs to keep the order in the clone print("setting LAN order by id") lans = dcdef['entities']['lans']['items'] new_order = sorted(lans, key=lambda lan: lan['id']) dcdef['entities']['lans']['items'] = new_order # now sort unordered NICs by MAC and save the dcdef # reason is, that NICs seem to be ordered by MAC, but API response # doesn't guarantee the order, which we need for re-creation print("setting NIC order by MAC") for server in dcdef['entities']['servers']['items']: print("- server {}".format(server['properties']['name'])) if 'nics' not in server['entities']: print(" server {} has no nics" .format(server['properties']['name'])) continue nics = server['entities']['nics']['items'] # print("NICs before {}".format(json.dumps(nics))) new_order = sorted(nics, key=lambda nic: nic['properties']['mac']) # print("NICs after {}".format(json.dumps(new_order))) server['entities']['nics']['items'] = new_order # end for(server) dcdef_file = outfile+'.json' print("write snapshot dc to {}".format(dcdef_file)) write_dc_definition(dcdef, dcdef_file) return 0 except KeyboardInterrupt: # handle keyboard interrupt return 0 except Exception: traceback.print_exc() sys.stderr.write("\n" + program_name + ": for help use --help\n") return 2
# limitations under the License. # pylint: disable=pointless-string-statement,reimported,wrong-import-position import os """List Datacenters """ from ionosenterprise.client import IonosEnterpriseService client = IonosEnterpriseService(username=os.getenv('IONOS_USERNAME'), password=os.getenv('IONOS_PASSWORD')) datacenters = client.list_datacenters() for d in datacenters['items']: vdc = client.get_datacenter(d['id']) name = vdc['properties']['name'] datacenter_id = vdc['id'] break """Get Datacenter """ from ionosenterprise.client import IonosEnterpriseService # noqa datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = IonosEnterpriseService(username='******', password='******') datacenter = client.get_datacenter(datacenter_id=datacenter_id) """Create Simple Datacenter """ from ionosenterprise.client import IonosEnterpriseService # noqa
def main(argv=None): # IGNORE:C0111 '''Command line options.''' if argv is None: argv = sys.argv else: sys.argv.extend(argv) program_name = os.path.basename(sys.argv[0]) program_version = "v%s" % __version__ program_build_date = str(__updated__) program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date) program_shortdesc = __import__('__main__').__doc__.split("\n")[1] program_license = '''%s Created by J.Buchhammer on %s. Copyright 2016 IONOS. All rights reserved. Licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 Distributed on an "AS IS" basis without warranties or conditions of any kind, either express or implied. USAGE ''' % (program_shortdesc, str(__date__)) try: # Setup argument parser parser = ArgumentParser( description=program_license, formatter_class=RawDescriptionHelpFormatter) parser.add_argument( '-u', '--user', dest='user', required=True, help='the login name') parser.add_argument( '-p', '--password', dest='password', help='the login password') parser.add_argument( '-d', '--datacenter', '--datacenterid', dest='datacenterid', nargs='?', const='*', help='show server/storage of datacenter(s)') parser.add_argument( '-i', '--image', dest='show_images', action="store_true", help='show images and snapshots') parser.add_argument( '-b', '--ipblock', dest='show_ipblocks', action="store_true", help='show reserved IP blocks') parser.add_argument( '-n', '--network', dest='show_networks', action="store_true", help='show network assignments') # parser.add_argument( # '-r', '--request', dest='show_requests', action="store_true", # help='show requests') parser.add_argument( "-v", "--verbose", dest="verbose", action="count", default=0, help="set verbosity level [default: %(default)s]") parser.add_argument( '-V', '--version', action='version', version=program_version_message) # Process arguments args = parser.parse_args() global verbose verbose = args.verbose # this is a global to be used in methods user = args.user password = args.password datacenterid = args.datacenterid print("Welcome to PB-API %s\n" % user) if password is None: password = getpass() if verbose > 0: print("Verbose mode on") print("using python ", sys.version_info) pbclient = IonosEnterpriseService(user, password) if datacenterid is not None: datacenters = {} if datacenterid == '*': # the default depth=1 is sufficient, higher values don't provide more details datacenters = pbclient.list_datacenters() else: datacenters['items'] = [] datacenters['items'] = [pbclient.get_datacenter(datacenterid, 1)] if verbose > 1: print(pp(datacenters)) print("retrieved %i datacenters " % len(datacenters['items'])) # dump inventory to file with open("pb_datacenter_inventory.csv", 'w') as csvfile: csvwriter = csv.writer(csvfile, delimiter=';', lineterminator='\n') csvwriter.writerow([ 'DCID', 'DCName', 'Loc', 'RscType', 'RscID', 'RscName', 'State', 'LicType', 'Cores', 'RAM', '# NICs', '# Volumes', '(Total) Storage', 'Connected to', 'Created', 'Modified' ]) for dc in datacenters['items']: try: dc_inv = get_dc_inventory(pbclient, dc) if verbose: print("DC %s has %i inventory entries" % (dc['id'], len(dc_inv))) for row in dc_inv: csvwriter.writerow(row) except Exception: traceback.print_exc() exit(2) # end for(datacenters) if args.show_images: with open("pb_datacenter_images.csv", 'w') as csvfile: csvwriter = csv.writer(csvfile, delimiter=';', lineterminator='\n') csvwriter.writerow([ 'Visibility', 'Loc', 'RscType', 'SubType', 'RscID', 'RscName', 'State', 'LicType', 'Size', 'Created', 'Modified' ]) img_inv = get_images(pbclient) for row in img_inv: csvwriter.writerow(row) snap_inv = get_snapshots(pbclient) for row in snap_inv: csvwriter.writerow(row) if args.show_ipblocks: with open("pb_datacenter_ipblocks.csv", 'w') as csvfile: csvwriter = csv.writer(csvfile, delimiter=';', lineterminator='\n') csvwriter.writerow([ 'Loc', 'RscType', 'RscID', 'State', 'Size', 'IP addresses']) ipblocks = get_ipblocks(pbclient) for row in ipblocks: csvwriter.writerow(row) # file is automatically closed after with block if args.show_networks: # the default depth=1 is sufficient, higher values don't provide more details datacenters = pbclient.list_datacenters() print("retrieved %i datacenters " % len(datacenters['items'])) with open("pb_datacenter_networks.csv", 'w') as csvfile: csvwriter = csv.writer(csvfile, delimiter=';', lineterminator='\n') csvwriter.writerow([ 'DCID', 'DCName', 'Loc', 'LAN ID', 'LAN name', 'public', 'State', '# NICs', 'NIC ID', 'MAC address', 'DHCP', 'IP(s)', 'NIC name', 'Firewall', 'Connected to', 'ID', 'Name']) for dc in datacenters['items']: try: dc_net = get_dc_network(pbclient, dc) if verbose: print("DC %s has %i network entries" % (dc['id'], len(dc_net))) for row in dc_net: csvwriter.writerow(row) except Exception: traceback.print_exc() exit(2) # end for(datacenters) # just for fun: # if args.show_requests: # get_requests(pbclient) print("%s finished w/o errors" % program_name) return 0 except KeyboardInterrupt: # handle keyboard interrupt return 0 except Exception: traceback.print_exc() sys.stderr.write("\n" + program_name + ": for help use --help\n") return 2