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)
Exemple #3
0
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
Exemple #9
0
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)
Exemple #12
0
# 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')