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 ProfitBricks GmbH. 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 = ProfitBricksService(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
class TestDatacenter(unittest.TestCase): @classmethod def setUpClass(self): self.resource = resource() self.client = ProfitBricksService( username=configuration.USERNAME, password=configuration.PASSWORD, headers=configuration.HEADERS) # Create test datacenter. self.datacenter = self.client.create_datacenter( datacenter=Datacenter(**self.resource['datacenter'])) @classmethod def tearDownClass(self): self.client.delete_datacenter(datacenter_id=self.datacenter['id']) def test_list(self): datacenters = self.client.list_datacenters() self.assertGreater(len(datacenters), 0) self.assertEqual(datacenters['items'][0]['type'], 'datacenter') def test_get(self): datacenter = self.client.get_datacenter( datacenter_id=self.datacenter['id']) assertRegex(self, datacenter['id'], self.resource['uuid_match']) self.assertEqual(datacenter['type'], 'datacenter') self.assertEqual(datacenter['id'], self.datacenter['id']) self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['description']) self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) def test_delete(self): datacenter = self.client.create_datacenter( datacenter=Datacenter(**self.resource['datacenter'])) wait_for_completion(self.client, datacenter, 'create_datacenter') response = self.client.delete_datacenter( datacenter_id=datacenter['id']) self.assertTrue(response) def test_update(self): datacenter = self.client.update_datacenter( datacenter_id=self.datacenter['id'], description=self.resource['datacenter']['name']+' - RENAME') wait_for_completion(self.client, datacenter, 'update_datacenter') datacenter = self.client.get_datacenter(datacenter_id=self.datacenter['id']) assertRegex(self, datacenter['id'], self.resource['uuid_match']) self.assertEqual(datacenter['id'], self.datacenter['id']) self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['name']+' - RENAME') self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) self.assertGreater(datacenter['properties']['version'], 1) def test_create_simple(self): datacenter = self.client.create_datacenter( datacenter=Datacenter(**self.resource['datacenter'])) wait_for_completion(self.client, datacenter, 'create_datacenter') assertRegex(self, datacenter['id'], self.resource['uuid_match']) self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['description']) self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) response = self.client.delete_datacenter( datacenter_id=datacenter['id']) self.assertTrue(response)
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 ProfitBricks GmbH. 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 = ProfitBricksService(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 len(images) == 0: 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 len(requests) != 0: 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
class TestDatacenter(unittest.TestCase): def setUp(self): self.datacenter = ProfitBricksService(username="******", password="******") def test_get_all(self): datacenters = self.datacenter.list_datacenters() self.assertEqual(len(datacenters), 4) self.assertEqual(datacenters["items"][0]["id"], datacenter_id) # self.assertEqual( # datacenters['items'][0]['properties']['name'], 'datacenter1') # self.assertEqual( # datacenters['items'][0]['properties']['description'], 'Description of my DC') # self.assertEqual( # datacenters['items'][0]['properties']['location'], 'de/fkb') # self.assertEqual( # datacenters['items'][0]['properties']['version'], 4) def test_get(self): datacenter = self.datacenter.get_datacenter(datacenter_id=datacenter_id) self.assertEqual(datacenter["id"], datacenter_id) self.assertEqual(datacenter["properties"]["name"], "datacenter1") self.assertEqual(datacenter["properties"]["description"], "Description of my DC") self.assertEqual(datacenter["properties"]["version"], 4) self.assertEqual(datacenter["properties"]["location"], "de/fkb") def test_delete(self): datacenter = self.datacenter.delete_datacenter(datacenter_id=datacenter_id) self.assertTrue(datacenter) def test_update(self): datacenter = self.datacenter.update_datacenter( datacenter_id=datacenter_id, name="Partially updated datacenter name" ) self.assertEqual(datacenter["id"], datacenter_id) self.assertEqual(datacenter["properties"]["name"], "datacenter1") self.assertEqual(datacenter["properties"]["description"], "Description of my DC") self.assertEqual(datacenter["properties"]["version"], 4) self.assertEqual(datacenter["properties"]["location"], "de/fkb") def test_create_simple(self): i = Datacenter(name="datacenter1", description="My New Datacenter", location="de/fkb") response = self.datacenter.create_datacenter(datacenter=i) self.assertEqual(response["id"], datacenter_id) self.assertEqual(response["properties"]["name"], "datacenter1") self.assertEqual(response["properties"]["description"], "My New Datacenter") self.assertEqual(response["properties"]["version"], 4) self.assertEqual(response["properties"]["location"], "de/fkb") def test_create_complex(self): """ Creates a complex Datacenter in a single request. """ fwrule1 = FirewallRule( name="Open SSH port", protocol="TCP", source_mac="01:23:45:67:89:00", port_range_start=22 ) fwrule2 = FirewallRule(name="Allow PING", protocol="ICMP", icmp_type=8, icmp_code=0) fw_rules = [fwrule1, fwrule2] nic1 = NIC(name="nic1", ips=["10.2.2.3"], dhcp="true", lan=1, firewall_active=True, firewall_rules=fw_rules) nic2 = NIC(name="nic2", ips=["10.2.3.4"], dhcp="true", lan=1, firewall_active=True, firewall_rules=fw_rules) nics = [nic1, nic2] volume1 = Volume(name="volume1", size=56, image="<IMAGE/SNAPSHOT-ID>", bus="VIRTIO") volume2 = Volume(name="volume2", size=56, image="<IMAGE/SNAPSHOT-ID>", bus="VIRTIO") volumes = [volume2] server1 = Server(name="server1", ram=4096, cores=4, nics=nics, create_volumes=[volume1]) servers = [server1] balancednics = ["<NIC-ID-1>", "<NIC-ID-2>"] loadbalancer1 = LoadBalancer(name="My LB", balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN(name="public Lan 4", public=True) lan2 = LAN(name="public Lan 4", public=True) lans = [lan1, lan2] d = Datacenter( name="datacenter1", description="my DC", location="de/fkb", servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans, ) response = self.datacenter.create_datacenter(datacenter=d) print(response) self.assertEqual(response["id"], datacenter_id) self.assertEqual(response["properties"]["name"], "My New Datacenter") self.assertEqual(response["properties"]["description"], "Production environment") self.assertEqual(response["properties"]["version"], 4) self.assertEqual(response["properties"]["location"], "de/fkb")
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os """List Datacenters """ from profitbricks.client import ProfitBricksService client = ProfitBricksService(username=os.getenv('PROFITBRICKS_USERNAME'), password=os.getenv('PROFITBRICKS_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 profitbricks.client import ProfitBricksService # noqa datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService(username='******', password='******') datacenter = client.get_datacenter(datacenter_id=datacenter_id) """Create Simple Datacenter """ from profitbricks.client import ProfitBricksService # 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 ProfitBricks GmbH. 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 = ProfitBricksService(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
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 ProfitBricks GmbH. 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 = ProfitBricksService(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(pbclient, 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(pbclient, 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
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 ProfitBricks GmbH. 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 = ProfitBricksService(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 len(images) == 0: 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 len(requests) != 0: 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
class TestIonosCloudAPI(unittest.TestCase): def setUp(self): self.client = ProfitBricksService(username=USERNAME, password=PASSWORD) self.public_key = get_public_key() def test_profitbricks(self): """ This is the actual test. It will consist from 4 different subtests, which are dependent from each other""" self._create_datacenter_subtest() self._frontend_is_up_and_running_subtest() self._update_data_center_subtest() self._file_creation_and_transfer_via_ssh_subtest() def _create_datacenter_subtest(self): """ Creates datacenter with specified paramters and checks it's state, location and name""" logging.info("Start datacenter creation") # create datacenter datacenter = describe_datacenter(self.client) response = self.client.create_datacenter(datacenter) # Wait for the data center and nested resources to finish provisioning self.client.wait_for_completion(response) self.datacenter_id = response['id'] logging.info("Datacenter creation finished") # Set the first LAN in datacenter to public logging.info("Start Lan update") response = self.client.update_lan(datacenter_id=self.datacenter_id, lan_id=1, name='Public LAN', public=True) self.client.wait_for_completion(response) logging.info("Lan update finished") # Check that datacenter was succesfully created response = self.client.get_datacenter(datacenter_id=self.datacenter_id) self.assertEqual(response['metadata']['state'], 'AVAILABLE', "Datacener's state is wrong") self.assertEqual(response['properties']['name'], DATACENTER_NAME, "Datacener's name is wrong") self.assertEqual(response['properties']['location'], LOCATION, "Datacener's location is wrong") def _frontend_is_up_and_running_subtest(self): """ Checks that Frontend server was up and is running after datacenter creation""" frontend = find_server(self.client, self.datacenter_id, FRONTEND_NAME) self.frontend_id = frontend['id'] self.assertEqual(frontend['metadata']['state'], 'AVAILABLE', "Frontend's state is wrong") self.assertEqual(frontend['properties']['vmState'], 'RUNNING', "Frontend's vmState is wrong") def _update_data_center_subtest(self): """ Checks that server is running with proper new paramters (ram, cores) after update""" frontend = find_server(self.client, self.datacenter_id, FRONTEND_NAME) self.assertEqual(frontend['properties']['cores'], DEFAULT_CORES_VALUES, "Frontend's core amount is wrong") self.assertEqual(frontend['properties']['ram'], DEFAULT_RAM_VALUE, "Frontend's ram amount is wrong") logging.info('Server update started') # update server with bigger cores and ram arguments response = self.client.update_server(self.datacenter_id, self.frontend_id, cores=UPDATED_CORES_VALUES, ram=UPDATED_RAM_VALUE) self.client.wait_for_completion(response) logging.info('Server update finished') # refresh Frontend server frontend = find_server(self.client, self.datacenter_id, FRONTEND_NAME) # check that cores and ram updated succesfully self.assertEqual(frontend['metadata']['state'], 'AVAILABLE', "Frontend's state is wrong") self.assertEqual(frontend['properties']['vmState'], 'RUNNING', "Frontend's vmState is wrong") self.assertEqual(frontend['properties']['cores'], UPDATED_CORES_VALUES, "Frontend's core amount is wrong") self.assertEqual(frontend['properties']['ram'], UPDATED_RAM_VALUE, "Frontend's ram amount is wrong") def _file_creation_and_transfer_via_ssh_subtest(self): """ Establishes connection via ssh to Frontend and creates file there. Than transfer this file to Backend via scp command. Checks that file was successfully transfered.""" # get public IP - to connect to it via ssh public_nic = find_nic(self.client, self.datacenter_id, self.frontend_id, PUBLIC_NIC_NAME) public_nic_ip = public_nic['properties']['ips'][0] # get backend's IP - to send file from Frontend here thorough local network. backend = find_server(self.client, self.datacenter_id, BACKEND_NAME) self.backend_id = backend['id'] backend_private_nic = find_nic(self.client, self.datacenter_id, self.backend_id, PRIVATE_NIC_NAME) private_nic_ip = backend_private_nic['properties']['ips'][0] # do ssh stuff result = ssh_to_frontend(public_nic_ip, private_nic_ip) self.assertIn(TEST_FILE_NAME, result)
"""List Datacenters """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='******', password='******') datacenters = client.list_datacenters() for d in datacenters['items']: vdc = client.get_datacenter(d['id']) name = vdc['properties']['name'] if name is for d in datacenters['items']: vdc = client.get_datacenter(d['id']) vdc['properties']['name'] if dc_name == vdc['properties']['name']: """Get Datacenter """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='******', password='******') datacenter = client.get_datacenter(
class TestDatacenter(unittest.TestCase): @classmethod def setUpClass(self): self.resource = resource() self.client = ProfitBricksService(username=configuration.USERNAME, password=configuration.PASSWORD, headers=configuration.HEADERS) # Create test datacenter. self.datacenter = self.client.create_datacenter(datacenter=Datacenter( **self.resource['datacenter'])) @classmethod def tearDownClass(self): self.client.delete_datacenter(datacenter_id=self.datacenter['id']) def test_list_datacenters(self): datacenters = self.client.list_datacenters() self.assertGreater(len(datacenters), 0) self.assertEqual(datacenters['items'][0]['type'], 'datacenter') def test_get_datacenter(self): datacenter = self.client.get_datacenter( datacenter_id=self.datacenter['id']) assertRegex(self, datacenter['id'], self.resource['uuid_match']) self.assertEqual(datacenter['type'], 'datacenter') self.assertEqual(datacenter['id'], self.datacenter['id']) self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['description']) self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) def test_get_failure(self): try: self.client.get_datacenter( datacenter_id='00000000-0000-0000-0000-000000000000') except PBNotFoundError as e: self.assertIn(self.resource['not_found_error'], e.content[0]['message']) def test_create_failure(self): try: datacenter = Datacenter(name=self.resource['datacenter']['name']) self.client.create_datacenter(datacenter) except PBError as e: self.assertIn( self.resource['missing_attribute_error'] % 'location', e.content[0]['message']) def test_remove_datacenter(self): datacenter = self.client.create_datacenter(datacenter=Datacenter( **self.resource['datacenter'])) self.client.wait_for_completion(datacenter) response = self.client.delete_datacenter( datacenter_id=datacenter['id']) self.assertTrue(response) def test_update_datacenter(self): datacenter = self.client.update_datacenter( datacenter_id=self.datacenter['id'], description=self.resource['datacenter']['name'] + ' - RENAME') self.client.wait_for_completion(datacenter) time.sleep(10) datacenter = self.client.get_datacenter( datacenter_id=self.datacenter['id']) assertRegex(self, datacenter['id'], self.resource['uuid_match']) self.assertEqual(datacenter['id'], self.datacenter['id']) self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['name'] + ' - RENAME') self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) self.assertGreater(datacenter['properties']['version'], 1) def test_create_simple(self): datacenter = self.client.create_datacenter(datacenter=Datacenter( **self.resource['datacenter'])) self.client.wait_for_completion(datacenter) self.assertEqual(datacenter['type'], 'datacenter') self.assertEqual(datacenter['properties']['name'], self.resource['datacenter']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter']['description']) self.assertEqual(datacenter['properties']['location'], self.resource['datacenter']['location']) response = self.client.delete_datacenter( datacenter_id=datacenter['id']) self.assertTrue(response) def test_create_composite(self): datacenter_resource = Datacenter( **self.resource['datacenter_composite']) datacenter_resource.servers = [Server(**self.resource['server'])] datacenter_resource.volumes = [Volume(**self.resource['volume'])] datacenter = self.client.create_datacenter( datacenter=datacenter_resource) self.client.wait_for_completion(datacenter) self.assertEqual(datacenter['type'], 'datacenter') self.assertEqual(datacenter['properties']['name'], self.resource['datacenter_composite']['name']) self.assertEqual(datacenter['properties']['description'], self.resource['datacenter_composite']['description']) self.assertEqual(datacenter['properties']['location'], self.resource['datacenter_composite']['location']) self.assertGreater(len(datacenter['entities']['servers']), 0) self.assertGreater(len(datacenter['entities']['volumes']), 0) response = self.client.delete_datacenter( datacenter_id=datacenter['id']) self.assertTrue(response)
# along with this program. If not, see <http://www.gnu.org/licenses/>. # # # from datetime import datetime, timedelta import config from slugify import slugify from pprint import pprint from profitbricks.client import ProfitBricksService client = ProfitBricksService( username=config.PB_USERNAME, password=config.PB_PASSWORD) # Get the PB Datacenter object datacenter = client.get_datacenter(datacenter_id=config.DATACENTER_ID) # Get a list of snapshots; this is global so can be done here snapshots = client.list_snapshots() # Process all found entities (servers) in for entity in datacenter['entities']['servers']['items']: # If this entity is not a server, continue (could be gateway, loadbalancer etc) if not entity['type'] == 'server': continue # Get this entitys server object from API server = client.get_server(datacenter_id=config.DATACENTER_ID,server_id=entity['id']) # Set the servername servername = server['properties']['name']
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 ProfitBricks GmbH. 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 = ProfitBricksService(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(pbclient, 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(pbclient, 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
class TestDatacenter(unittest.TestCase): def setUp(self): self.datacenter = ProfitBricksService( username='******', password='******') def test_get_all(self): datacenters = self.datacenter.list_datacenters() self.assertEqual(len(datacenters), 4) self.assertEqual(datacenters['items'][0]['id'], datacenter_id) # self.assertEqual( # datacenters['items'][0]['properties']['name'], 'datacenter1') # self.assertEqual( # datacenters['items'][0]['properties']['description'], 'Description of my DC') # self.assertEqual( # datacenters['items'][0]['properties']['location'], 'de/fkb') # self.assertEqual( # datacenters['items'][0]['properties']['version'], 4) def test_get(self): datacenter = self.datacenter.get_datacenter( datacenter_id=datacenter_id) self.assertEqual(datacenter['id'], datacenter_id) self.assertEqual(datacenter['properties']['name'], 'datacenter1') self.assertEqual(datacenter['properties']['description'], 'Description of my DC') self.assertEqual(datacenter['properties']['version'], 4) self.assertEqual(datacenter['properties']['location'], 'de/fkb') def test_delete(self): datacenter = self.datacenter.delete_datacenter( datacenter_id=datacenter_id) self.assertTrue(datacenter) def test_update(self): datacenter = self.datacenter.update_datacenter( datacenter_id=datacenter_id, name='Partially updated datacenter name') self.assertEqual(datacenter['id'], datacenter_id) self.assertEqual(datacenter['properties']['name'], 'datacenter1') self.assertEqual(datacenter['properties']['description'], 'Description of my DC') self.assertEqual(datacenter['properties']['version'], 4) self.assertEqual(datacenter['properties']['location'], 'de/fkb') def test_create_simple(self): i = Datacenter( name='datacenter1', description='My New Datacenter', location='de/fkb' ) response = self.datacenter.create_datacenter(datacenter=i) self.assertEqual(response['id'], datacenter_id) self.assertEqual(response['properties']['name'], 'My New Datacenter') self.assertEqual(response['properties']['description'], 'Production environment') self.assertEqual(response['properties']['version'], 4) self.assertEqual(response['properties']['location'], 'de/fkb') def test_create_complex(self): """ Creates a complex Datacenter in a single request. """ fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nics = [nic1, nic2] volume1 = Volume( name='volume1', size=56, image='<IMAGE/SNAPSHOT-ID>', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='<IMAGE/SNAPSHOT-ID>', bus='VIRTIO' ) volumes = [volume2] server1 = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=[volume1] ) servers = [server1] balancednics = ['<NIC-ID-1>', '<NIC-ID-2>'] loadbalancer1 = LoadBalancer( name='My LB', balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 4', public=True ) lans = [lan1, lan2] d = Datacenter( name='datacenter1', description='my DC', location='de/fkb', servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans ) response = self.datacenter.create_datacenter(datacenter=d) print(response) self.assertEqual(response['id'], datacenter_id) self.assertEqual(response['properties']['name'], 'My New Datacenter') self.assertEqual(response['properties']['description'], 'Production environment') self.assertEqual(response['properties']['version'], 4) self.assertEqual(response['properties']['location'], 'de/fkb')