Beispiel #1
0
    def create(self,
               name,
               virttype=None,
               profile='',
               flavor=None,
               plan='kvirt',
               cpumodel='Westmere',
               cpuflags=[],
               cpupinning=[],
               numcpus=2,
               memory=512,
               guestid='guestrhel764',
               pool='default',
               image=None,
               disks=[{
                   'size': 10
               }],
               disksize=10,
               diskthin=True,
               diskinterface='virtio',
               nets=['default'],
               iso=None,
               vnc=False,
               cloudinit=True,
               reserveip=False,
               reservedns=False,
               reservehost=False,
               start=True,
               keys=None,
               cmds=[],
               ips=None,
               netmasks=None,
               gateway=None,
               nested=True,
               dns=None,
               domain=None,
               tunnel=False,
               files=[],
               enableroot=True,
               alias=[],
               overrides={},
               tags=[],
               storemetadata=False,
               sharedfolders=[],
               kernel=None,
               initrd=None,
               cmdline=None,
               cpuhotplug=False,
               memoryhotplug=False,
               numamode=None,
               numa=[],
               pcidevices=[],
               tpm=False,
               placement=[],
               autostart=False,
               rng=False,
               metadata={},
               securitygroups=[]):
        """

        :param name:
        :param virttype:
        :param profile:
        :param flavor:
        :param plan:
        :param cpumodel:
        :param cpuflags:
        :param cpupinning:
        :param numcpus:
        :param memory:
        :param guestid:
        :param pool:
        :param image:
        :param disks:
        :param disksize:
        :param diskthin:
        :param diskinterface:
        :param nets:
        :param iso:
        :param vnc:
        :param cloudinit:
        :param reserveip:
        :param reservedns:
        :param reservehost:
        :param start:
        :param keys:
        :param cmds:
        :param ips:
        :param netmasks:
        :param gateway:
        :param nested:
        :param dns:
        :param domain:
        :param tunnel:
        :param files:
        :param enableroot:
        :param alias:
        :param overrides:
        :param tags:
        :param cpuhotplug:
        :param memoryhotplug:
        :param numamode:
        :param numa:
        :param pcidevices:
        :param tpm:
        :return:
        """
        reservation_id = overrides.get('hardware_reservation_id')
        if reservation_id is not None:
            reservations = self.conn.list_hardware_reservations(self.project)
            if not reservations:
                return {
                    'result': 'failure',
                    'reason': "No reserved hardware found"
                }
            elif reservation_id != 'next-available':
                matching_ids = [
                    r.id for r in reservations
                    if r.id == reservation_id or r.short_id == reservation_id
                ]
                if not matching_ids:
                    return {
                        'result':
                        'failure',
                        'reason':
                        "Reserved hardware with id %s not found" %
                        reservation_id
                    }
                else:
                    reservation_id = matching_ids[0]
        ipxe_script_url = None
        userdata = None
        networkid = None
        networkids = []
        vlan = False
        for index, network in enumerate(nets):
            if index > 1:
                warning("Ignoring net higher than %s" % index)
                break
            if isinstance(network, str):
                networkname = network
            elif isinstance(network, dict) and 'name' in network:
                networkname = network['name']
            if networkname != 'default':
                networks = [
                    n for n in self.conn.list_vlans(self.project)
                    if n.id == networkname or (n.description is not None and
                                               n.description == networkname)
                ]
                if not networks:
                    return {
                        'result': 'failure',
                        'reason': "Network %s not found" % networkname
                    }
                else:
                    vlan = True
                    networkid = networks[0].id
            else:
                networkid = None
            networkids.append(networkid)
        if image is not None and not common.needs_ignition(image):
            if '_' not in image and image in [
                    'rhel8', 'rhel7', 'centos7', 'centos8'
            ]:
                image = image[:-1] + '_' + image[-1:]
                pprint("Using image %s" % image)
            found = False
            for img in self.conn.list_operating_systems():
                if img.slug == image:
                    found = True
            if not found:
                msg = "image %s doesn't exist" % image
                return {'result': 'failure', 'reason': msg}
        elif image is None:
            ipxe_script_url = overrides.get('ipxe_script_url')
            if ipxe_script_url is None:
                return {
                    'result': 'failure',
                    'reason': 'You need to define ipxe_script_url as parameter'
                }
            image = 'custom_ipxe'
        else:
            ignition_url = overrides.get('ignition_url')
            if ignition_url is None:
                if self.tunnelhost is not None:
                    ignition_url = "http://%s/%s.ign" % (self.tunnelhost, name)
                else:
                    return {
                        'result': 'failure',
                        'reason':
                        'You need to define ignition_url as parameter'
                    }
            url = IMAGES[image]
            if 'rhcos' in image:
                if 'commit_id' in overrides:
                    kernel, initrd, metal = common.get_commit_rhcos_metal(
                        overrides['commit_id'])
                else:
                    kernel, initrd, metal = common.get_latest_rhcos_metal(url)
            elif 'fcos' in image:
                kernel, initrd, metal = common.get_latest_fcos_metal(url)
            interface = 'eth0' if 'fcos' in image else 'ens3f0'
            userdata = self._ipxe(kernel, initrd, metal, ignition_url,
                                  interface)
            version = common.ignition_version(image)
            ignitiondir = '/tmp'
            ipv6 = []
            ignitiondata = common.ignition(name=name,
                                           keys=keys,
                                           cmds=cmds,
                                           nets=nets,
                                           gateway=gateway,
                                           dns=dns,
                                           domain=domain,
                                           reserveip=reserveip,
                                           files=files,
                                           enableroot=enableroot,
                                           overrides=overrides,
                                           version=version,
                                           plan=plan,
                                           ipv6=ipv6,
                                           image=image)
            image = 'custom_ipxe'
            with open('%s/%s.ign' % (ignitiondir, name), 'w') as ignitionfile:
                ignitionfile.write(ignitiondata)
            if self.tunnelhost is not None:
                pprint("Copying ignition data to %s" % self.tunnelhost)
                scpcmd = "scp -qP %s /tmp/%s.ign %s@%s:%s/%s.ign" % (
                    self.tunnelport, name, self.tunneluser, self.tunnelhost,
                    self.tunneldir, name)
                os.system(scpcmd)
        if flavor is None:
            # if f[1] >= numcpus and f[2] >= memory:
            minmemory = 512000
            for f in self.conn.list_plans():
                if not f.specs:
                    continue
                flavorname = f.name
                # skip this flavor until we know where it can be launched
                if flavorname == 'c3.small.x86' or (
                        vlan
                        and flavorname in ['t1.small.x86', 'c1.small.x86']):
                    continue
                flavorcpus = int(f.specs['cpus'][0]['count'])
                flavormemory = int(f.specs['memory']['total'].replace(
                    'GB', '')) * 1024
                if flavorcpus >= 1 and flavormemory >= memory and flavormemory < minmemory:
                    flavor = flavorname
                    minmemory = flavormemory
                    validfacilities = f.available_in
            if flavor is None:
                return {
                    'result': 'failure',
                    'reason': 'Couldnt find flavor matching requirements'
                }
            pprint("Using flavor %s" % flavor)
        else:
            flavors = [f for f in self.conn.list_plans() if f.slug == flavor]
            if not flavors:
                return {
                    'result': 'failure',
                    'reason': 'Flavors %s not found' % flavor
                }
            else:
                validfacilities = flavors[0].available_in
        features = ['tpm'] if tpm else []
        if cloudinit and userdata is None:
            userdata = common.cloudinit(name=name,
                                        keys=keys,
                                        cmds=cmds,
                                        nets=nets,
                                        gateway=gateway,
                                        dns=dns,
                                        domain=domain,
                                        reserveip=reserveip,
                                        files=files,
                                        enableroot=enableroot,
                                        overrides=overrides,
                                        fqdn=True,
                                        storemetadata=storemetadata)[0]
        validfacilities = [
            os.path.basename(e['href']) for e in validfacilities
        ]
        validfacilities = [
            f.code for f in self.conn.list_facilities()
            if f.id in validfacilities
        ]
        if not validfacilities:
            return {
                'result': 'failure',
                'reason': 'no valid facility found for flavor %s' % flavor
            }
        facility = overrides.get('facility')
        if facility is not None:
            matchingfacilities = [
                f for f in self.conn.list_facilities() if f.slug == facility
            ]
            if not matchingfacilities:
                return {
                    'result': 'failure',
                    'reason': 'Facility %s not found' % facility
                }
            if facility not in validfacilities:
                return {
                    'result':
                    'failure',
                    'reason':
                    'Facility %s not allowed. You should choose between %s' %
                    (facility, ','.join(validfacilities))
                }
        elif self.facility is not None:
            if self.facility not in validfacilities:
                return {
                    'result':
                    'failure',
                    'reason':
                    'Facility %s not allowed. You should choose between %s' %
                    (self.facility, ','.join(validfacilities))
                }
            facility = self.facility
        else:
            facility = validfacilities[0]
        tags = ['project_%s' % self.project]
        if userdata is not None and 'ignition' in userdata:
            tags.append("kernel_%s" % os.path.basename(kernel))
        for entry in [field for field in metadata if field in METADATA_FIELDS]:
            tags.append("%s_%s" % (entry, metadata[entry]))
        # ip_addresses = [{"address_family": 4, "public": True}, {"address_family": 6, "public": False}]
        data = {
            'project_id': self.project,
            'hostname': name,
            'plan': flavor,
            'facility': facility,
            'operating_system': image,
            'userdata': userdata,
            'features': features,
            'tags': tags
        }
        if ipxe_script_url is not None:
            data['ipxe_script_url'] = ipxe_script_url
        if reservation_id is not None:
            data['hardware_reservation_id'] = reservation_id
        try:
            device = self.conn.create_device(**data)
        except Exception as e:
            return {'result': 'failure', 'reason': e}
        for networkid in networkids:
            if networkid is None:
                continue
            elif 'cluster' in overrides and name.startswith(
                    "%s-" % overrides['cluster']):
                warning(
                    "Not applying custom vlan to speed process for openshift..."
                )
                warning("This will be applied manually later...")
                continue
            status = 'provisioning'
            while status != 'active':
                status = self.info(name).get('status')
                pprint("Waiting 5s for %s to be active..." % name)
                sleep(5)
            device_port_id = device["network_ports"][2]["id"]
            self.conn.disbond_ports(device_port_id, False)
            self.conn.assign_port(device_port_id, networkid)
            break
        return {'result': 'success'}
Beispiel #2
0
    def create(self,
               name,
               virttype='kvm',
               profile='',
               plan='kvirt',
               flavor=None,
               cpumodel='Westmere',
               cpuflags=[],
               numcpus=2,
               memory=512,
               guestid='guestrhel764',
               pool='default',
               template=None,
               disks=[{
                   'size': 10
               }],
               disksize=10,
               diskthin=True,
               diskinterface='virtio',
               nets=['default'],
               iso=None,
               vnc=False,
               cloudinit=True,
               reserveip=False,
               reservedns=False,
               reservehost=False,
               start=True,
               keys=None,
               cmds=[],
               ips=None,
               netmasks=None,
               gateway=None,
               nested=True,
               dns=None,
               domain=None,
               tunnel=False,
               files=[],
               enableroot=True,
               alias=[],
               overrides={},
               tags=None):
        """

        :param name:
        :param virttype:
        :param profile:
        :param plan:
        :param flavor:
        :param cpumodel:
        :param cpuflags:
        :param numcpus:
        :param memory:
        :param guestid:
        :param pool:
        :param template:
        :param disks:
        :param disksize:
        :param diskthin:
        :param diskinterface:
        :param nets:
        :param iso:
        :param vnc:
        :param cloudinit:
        :param reserveip:
        :param reservedns:
        :param reservehost:
        :param start:
        :param keys:
        :param cmds:
        :param ips:
        :param netmasks:
        :param gateway:
        :param nested:
        :param dns:
        :param domain:
        :param tunnel:
        :param files:
        :param enableroot:
        :param alias:
        :param overrides:
        :param tags:
        :return:
        """
        glance = self.glance
        nova = self.nova
        neutron = self.neutron
        try:
            nova.servers.find(name=name)
            common.pprint("VM %s already exists" % name, color='red')
            return {
                'result': 'failure',
                'reason': "VM %s already exists" % name
            }
        except:
            pass
        allflavors = [f for f in nova.flavors.list()]
        allflavornames = [flavor.name for flavor in allflavors]
        if flavor is None:
            flavors = [
                flavor for flavor in allflavors
                if flavor.ram >= memory and flavor.vcpus == numcpus
            ]
            flavor = flavors[0] if flavors else nova.flavors.find(
                name="m1.tiny")
            common.pprint("Using flavor %s" % flavor.name, color='green')
        elif flavor not in allflavornames:
            return {
                'result': 'failure',
                'reason': "Flavor %s not found" % flavor
            }
        else:
            flavor = nova.flavors.find(name=flavor)
        nics = []
        for net in nets:
            if isinstance(net, str):
                netname = net
            elif isinstance(net, dict) and 'name' in net:
                netname = net['name']
            try:
                net = nova.neutron.find_network(name=netname)
            except Exception as e:
                common.pprint(e, color='red')
                return {
                    'result': 'failure',
                    'reason': "Network %s not found" % netname
                }
            nics.append({'net-id': net.id})
        image = None
        if template is not None:
            images = [
                image for image in glance.images.list()
                if image.name == template
            ]
            if images:
                image = images[0]
            else:
                msg = "you don't have template %s" % template
                return {'result': 'failure', 'reason': msg}
        block_dev_mapping = {}
        for index, disk in enumerate(disks):
            imageref = None
            diskname = "%s-disk%s" % (name, index)
            letter = chr(index + ord('a'))
            if isinstance(disk, int):
                disksize = disk
                diskthin = True
            elif isinstance(disk, str) and disk.isdigit():
                disksize = int(disk)
                diskthin = True
            elif isinstance(disk, dict):
                disksize = disk.get('size', '10')
                diskthin = disk.get('thin', True)
            if index == 0 and template is not None:
                if not diskthin:
                    imageref = image.id
                else:
                    continue
            newvol = self.cinder.volumes.create(name=diskname,
                                                size=disksize,
                                                imageRef=imageref)
            block_dev_mapping['vd%s' % letter] = newvol.id
        key_name = 'kvirt'
        keypairs = [k.name for k in nova.keypairs.list()]
        if key_name not in keypairs:
            homekey = None
            if not os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME'])\
                    and not os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME']):
                print(
                    "neither id_rsa.pub or id_dsa public keys found in your .ssh directory, you might have trouble "
                    "accessing the vm")
            else:
                if os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME']):
                    homekey = open("%s/.ssh/id_rsa.pub" %
                                   os.environ['HOME']).read()
                else:
                    homekey = open("%s/.ssh/id_dsa.pub" %
                                   os.environ['HOME']).read()
                nova.keypairs.create(key_name, homekey)
        elif keypairs:
            key_name = keypairs[0]
            if key_name != 'kvirt':
                common.pprint('Using keypair %s' % key_name, color='green')
        else:
            common.pprint(
                'Couldnt locate or create keypair for use. Leaving...',
                color='red')
            return {'result': 'failure', 'reason': "No usable keypair found"}
        meta = {'plan': plan, 'profile': profile}
        userdata = None
        if cloudinit:
            if template is not None and (template.startswith('coreos')
                                         or template.startswith('rhcos')):
                etcd = None
                userdata = common.ignition(name=name,
                                           keys=keys,
                                           cmds=cmds,
                                           nets=nets,
                                           gateway=gateway,
                                           dns=dns,
                                           domain=domain,
                                           reserveip=reserveip,
                                           files=files,
                                           enableroot=enableroot,
                                           overrides=overrides,
                                           etcd=etcd)
            else:
                common.cloudinit(name=name,
                                 keys=keys,
                                 cmds=cmds,
                                 nets=nets,
                                 gateway=gateway,
                                 dns=dns,
                                 domain=domain,
                                 reserveip=reserveip,
                                 files=files,
                                 enableroot=enableroot,
                                 overrides=overrides,
                                 iso=False)
            userdata = open('/tmp/user-data', 'r').read().strip()
        instance = nova.servers.create(name=name,
                                       image=image,
                                       flavor=flavor,
                                       key_name=key_name,
                                       nics=nics,
                                       meta=meta,
                                       userdata=userdata,
                                       block_device_mapping=block_dev_mapping)
        tenant_id = instance.tenant_id
        floating_ips = [
            f['id'] for f in neutron.list_floatingips()['floatingips']
            if f['port_id'] is None
        ]
        if not floating_ips:
            network_id = None
            networks = [
                n for n in neutron.list_networks()['networks']
                if n['router:external']
            ]
            if networks:
                network_id = networks[0]['id']
            if network_id is not None and tenant_id is not None:
                args = dict(floating_network_id=network_id,
                            tenant_id=tenant_id)
                floating_ip = neutron.create_floatingip(
                    body={'floatingip': args})
                floatingip_id = floating_ip['floatingip']['id']
                floatingip_ip = floating_ip['floatingip'][
                    'floating_ip_address']
                common.pprint('Assigning new floating ip %s for this vm' %
                              floatingip_ip,
                              color='green')
        else:
            floatingip_id = floating_ips[0]
        fixed_ip = None
        timeout = 0
        while fixed_ip is None:
            common.pprint("Waiting 5 seconds for vm to get an ip",
                          color='green')
            sleep(5)
            timeout += 5
            if timeout >= 80:
                common.pprint("Time out waiting for vm to get an ip",
                              color='red')
                break
            vm = nova.servers.get(instance.id)
            for key in list(vm.addresses):
                entry1 = vm.addresses[key]
                for entry2 in entry1:
                    if entry2['OS-EXT-IPS:type'] == 'fixed':
                        fixed_ip = entry2['addr']
                        break
        if fixed_ip is not None:
            fixedports = [
                i['id'] for i in neutron.list_ports()['ports'] if
                i['fixed_ips'] and i['fixed_ips'][0]['ip_address'] == fixed_ip
            ]
            port_id = fixedports[0]
            neutron.update_floatingip(floatingip_id,
                                      {'floatingip': {
                                          'port_id': port_id
                                      }})
        securitygroups = [
            s for s in neutron.list_security_groups()['security_groups']
            if s['name'] == 'default' and s['tenant_id'] == tenant_id
        ]
        if securitygroups:
            securitygroup = securitygroups[0]
            securitygroupid = securitygroup['id']
            sshrule = {
                'security_group_rule': {
                    'direction': 'ingress',
                    'security_group_id': securitygroupid,
                    'port_range_min': '22',
                    'port_range_max': '22',
                    'protocol': 'tcp',
                    'remote_group_id': None,
                    'remote_ip_prefix': '0.0.0.0/0'
                }
            }
            icmprule = {
                'security_group_rule': {
                    'direction': 'ingress',
                    'security_group_id': securitygroupid,
                    'protocol': 'icmp',
                    'remote_group_id': None,
                    'remote_ip_prefix': '0.0.0.0/0'
                }
            }
            try:
                neutron.create_security_group_rule(sshrule)
                neutron.create_security_group_rule(icmprule)
            except:
                pass
        return {'result': 'success'}
Beispiel #3
0
    def create(self, name, virttype='kvm', profile='', flavor=None, plan='kvirt', cpumodel='Westmere', cpuflags=[],
               numcpus=2, memory=512, guestid='guestrhel764', pool='default', template=None, disks=[{'size': 10}],
               disksize=10, diskthin=True, diskinterface='virtio', nets=['default'], iso=None, vnc=False,
               cloudinit=True, reserveip=False, reservedns=False, reservehost=False, start=True, keys=None, cmds=[],
               ips=None, netmasks=None, gateway=None, nested=True, dns=None, domain=None, tunnel=False, files=[],
               enableroot=True, alias=[], overrides={}, tags=None, dnshost=None, storemetadata=False):
        """

        :param name:
        :param virttype:
        :param profile:
        :param flavor:
        :param plan:
        :param cpumodel:
        :param cpuflags:
        :param numcpus:
        :param memory:
        :param guestid:
        :param pool:
        :param template:
        :param disks:
        :param disksize:
        :param diskthin:
        :param diskinterface:
        :param nets:
        :param iso:
        :param vnc:
        :param cloudinit:
        :param reserveip:
        :param reservedns:
        :param reservehost:
        :param start:
        :param keys:
        :param cmds:
        :param ips:
        :param netmasks:
        :param gateway:
        :param nested:
        :param dns:
        :param domain:
        :param tunnel:
        :param files:
        :param enableroot:
        :param alias:
        :param overrides:
        :param tags:
        :return:
        """
        template = self.__evaluate_template(template)
        keypair = self.keypair
        if template is not None and not template.startswith('ami-'):
                return {'result': 'failure', 'reason': 'Invalid template %s' % template}
        defaultsubnetid = None
        if flavor is None:
            matchingflavors = [f for f in static_flavors if static_flavors[f]['cpus'] >= numcpus and
                               static_flavors[f]['memory'] >= memory]
            if matchingflavors:
                flavor = matchingflavors[0]
                common.pprint("Using instance type %s" % flavor, color='green')
            else:
                return {'result': 'failure', 'reason': 'Couldnt find instance type matching requirements'}
        conn = self.conn
        tags = [{'ResourceType': 'instance',
                 'Tags': [{'Key': 'Name', 'Value': name}, {'Key': 'plan', 'Value': plan},
                          {'Key': 'hostname', 'Value': name}, {'Key': 'profile', 'Value': profile}]}]
        if keypair is None:
            keypair = 'kvirt_%s' % self.access_key_id
        keypairs = [k for k in conn.describe_key_pairs()['KeyPairs'] if k['KeyName'] == keypair]
        if not keypairs:
            common.pprint("Importing your public key as %s" % keypair, color='green')
            if not os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME'])\
                    and not os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME'])\
                    and not os.path.exists("%s/.kcli/id_rsa.pub" % os.environ['HOME'])\
                    and not os.path.exists("%s/.kcli/id_dsa.pub" % os.environ['HOME']):
                common.pprint("No public key found. Leaving", color='red')
                return {'result': 'failure', 'reason': 'No public key found'}
            elif os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME']):
                homekey = open("%s/.ssh/id_rsa.pub" % os.environ['HOME']).read()
            elif os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME']):
                homekey = open("%s/.ssh/id_dsa.pub" % os.environ['HOME']).read()
            elif os.path.exists("%s/.kcli/id_rsa.pub" % os.environ['HOME']):
                homekey = open("%s/.kcli/id_rsa.pub" % os.environ['HOME']).read()
            else:
                homekey = open("%s/.kcli/id_dsa.pub" % os.environ['HOME']).read()
            conn.import_key_pair(KeyName=keypair, PublicKeyMaterial=homekey)
        if cloudinit:
            if template is not None and (template.startswith('coreos') or template.startswith('rhcos')):
                etcd = None
                userdata = common.ignition(name=name, keys=keys, cmds=cmds, nets=nets, gateway=gateway, dns=dns,
                                           domain=domain, reserveip=reserveip, files=files, enableroot=enableroot,
                                           overrides=overrides, etcd=etcd)
            else:
                common.cloudinit(name=name, keys=keys, cmds=cmds, nets=nets, gateway=gateway, dns=dns, domain=domain,
                                 reserveip=reserveip, files=files, enableroot=enableroot, overrides=overrides,
                                 iso=False, fqdn=True, storemetadata=storemetadata)
                userdata = open('/tmp/user-data', 'r').read()
        else:
            userdata = ''
        networkinterfaces = []
        blockdevicemappings = []
        privateips = []
        for index, net in enumerate(nets):
            networkinterface = {'DeleteOnTermination': True, 'Description': "eth%s" % index, 'DeviceIndex': index,
                                'Groups': ['string'], 'SubnetId': 'string'}
            ip = None
            if isinstance(net, str):
                netname = net
                netpublic = True
            elif isinstance(net, dict) and 'name' in net:
                netname = net['name']
                ip = net.get('ip')
                alias = net.get('alias')
                netpublic = net.get('public', True)
            networkinterface['AssociatePublicIpAddress'] = netpublic if index == 0 else False
            if netname == 'default':
                if defaultsubnetid is not None:
                    netname = defaultsubnetid
                else:
                    # Filters = [{'Name': 'isDefault', 'Values': ['True']}]
                    # vpcs = conn.describe_vpcs(Filters=Filters)
                    vpcs = conn.describe_vpcs()
                    vpcid = [vpc['VpcId'] for vpc in vpcs['Vpcs'] if vpc['IsDefault']][0]
                    # Filters = [{'Name': 'vpc-id', 'Values': [vpcid]}, {'Name': 'default-for-az', 'Values': ['True']}]
                    subnets = conn.describe_subnets()
                    subnetid = [subnet['SubnetId'] for subnet in subnets['Subnets']
                                if subnet['DefaultForAz'] and subnet['VpcId'] == vpcid][0]
                    netname = subnetid
                    defaultsubnetid = netname
                    common.pprint("Using subnet %s as default" % defaultsubnetid, color='green')
            if ips and len(ips) > index and ips[index] is not None:
                ip = ips[index]
                if index == 0:
                    networkinterface['PrivateIpAddress'] = ip
                    privateip = {'Primary': True, 'PrivateIpAddress': ip}
                else:
                    privateip = {'Primary': False, 'PrivateIpAddress': ip}
                privateips = privateips.append(privateip)
            networkinterface['SubnetId'] = netname
            networkinterfaces.append(networkinterface)
        if len(privateips) > 1:
            networkinterface['PrivateIpAddresses'] = privateips
        for index, disk in enumerate(disks):
            letter = chr(index + ord('a'))
            devicename = '/dev/sd%s1' % letter if index == 0 else '/dev/sd%s' % letter
            blockdevicemapping = {'DeviceName': devicename, 'Ebs': {'DeleteOnTermination': True,
                                                                    'VolumeType': 'standard'}}
            if isinstance(disk, int):
                disksize = disk
            elif isinstance(disk, str) and disk.isdigit():
                disksize = str(disk)
            elif isinstance(disk, dict):
                disksize = disk.get('size', '10')
                blockdevicemapping['Ebs']['VolumeType'] = disk.get('type', 'standard')
            blockdevicemapping['Ebs']['VolumeSize'] = disksize
            blockdevicemappings.append(blockdevicemapping)
        if reservedns and domain is not None:
            tags[0]['Tags'].append({'Key': 'domain', 'Value': domain})
        if dnshost is not None:
            tags[0]['Tags'].append({'Key': 'dnshost', 'Value': dnshost})
        conn.run_instances(ImageId=template, MinCount=1, MaxCount=1, InstanceType=flavor,
                           KeyName=keypair, BlockDeviceMappings=blockdevicemappings,
                           UserData=userdata, TagSpecifications=tags)
        common.pprint("%s created on aws" % name, color='green')
        if reservedns and domain is not None:
            self.reserve_dns(name, nets=nets, domain=domain, alias=alias, instanceid=name)
        return {'result': 'success'}
Beispiel #4
0
    def create(self,
               name,
               virttype='kvm',
               profile='',
               flavor=None,
               plan='kvirt',
               cpumodel='Westmere',
               cpuflags=[],
               numcpus=2,
               memory=512,
               guestid='guestrhel764',
               pool='default',
               image=None,
               disks=[{
                   'size': 10
               }],
               disksize=10,
               diskthin=True,
               diskinterface='virtio',
               nets=['default'],
               iso=None,
               vnc=False,
               cloudinit=True,
               reserveip=False,
               reservedns=False,
               reservehost=False,
               start=True,
               keys=None,
               cmds=[],
               ips=None,
               netmasks=None,
               gateway=None,
               nested=True,
               dns=None,
               domain=None,
               tunnel=False,
               files=[],
               enableroot=True,
               alias=[],
               overrides={},
               tags={},
               dnsclient=None,
               storemetadata=False,
               sharedfolders=[],
               kernel=None,
               initrd=None,
               cmdline=None,
               placement=[],
               autostart=False):
        """

        :param name:
        :param virttype:
        :param profile:
        :param flavor:
        :param plan:
        :param cpumodel:
        :param cpuflags:
        :param numcpus:
        :param memory:
        :param guestid:
        :param pool:
        :param image:
        :param disks:
        :param disksize:
        :param diskthin:
        :param diskinterface:
        :param nets:
        :param iso:
        :param vnc:
        :param cloudinit:
        :param reserveip:
        :param reservedns:
        :param reservehost:
        :param start:
        :param keys:
        :param cmds:
        :param ips:
        :param netmasks:
        :param gateway:
        :param nested:
        :param dns:
        :param domain:
        :param tunnel:
        :param files:
        :param enableroot:
        :param alias:
        :param overrides:
        :param tags:
        :return:
        """
        plandir = "/tmp/%s" % plan
        namedir = "%s/%s" % (plandir, name)
        if not os.path.exists(plandir):
            common.pprint("Generating assets in %s" % plandir)
            os.mkdir(plandir)
        if os.path.exists(namedir):
            rmtree(namedir)
        os.mkdir(namedir)
        if cloudinit:
            if image is not None and ('coreos' in image
                                      or image.startswith('rhcos')):
                common.pprint("Data provided for a %s image" % image)
                version = '3.0.0' if image.startswith(
                    'fedora-coreos') else '2.2.0'
                etcd = None
                ignitiondata = common.ignition(name=name,
                                               keys=keys,
                                               cmds=cmds,
                                               nets=nets,
                                               gateway=gateway,
                                               dns=dns,
                                               domain=domain,
                                               reserveip=reserveip,
                                               files=files,
                                               enableroot=enableroot,
                                               overrides=overrides,
                                               etcd=etcd,
                                               version=version,
                                               plan=plan)
                with open('%s/%s.ign' % (namedir, name), 'w') as ignitionfile:
                    ignitionfile.write(ignitiondata)
            else:
                _files = yaml.safe_load(
                    common.process_files(files=files, overrides=overrides))
                cmds = common.process_cmds(cmds, overrides).replace('- ', '')
                if cmds != "":
                    with open("%s/cmds.sh" % (namedir), "w") as f:
                        f.write(cmds)
                copycmds = ""
                permissioncmds = ""
                if _files is not None:
                    for entry in _files:
                        owner = entry.get("owner", 'root')
                        path = entry["path"]
                        origin = os.path.basename(entry["path"])
                        permissions = entry.get("permissions")
                        content = entry["content"]
                        with open("%s/%s" % (namedir, os.path.basename(path)),
                                  "w") as f:
                            f.write(content)
                        copycmds += "scp %s $host:%s\n" % (origin, path)
                        if owner != "root:root":
                            permissioncmds += "chown %s %s\n" % (owner, path)
                        if permissions is not None and permissions != '0600':
                            permissioncmds += "chmod %s %s\n" % (permissions,
                                                                 path)
                with open("%s/launch.sh" % namedir, "w") as f:
                    if 'host' in overrides:
                        host = overrides["host"]
                    else:
                        common.pprint("Set host in launch.sh", color="blue")
                        host = ""
                    user = "******" % overrides[
                        "user"] if "user" in overrides else "root"
                    f.write("#!/bin/bash\nhost=\"%s%s\"\n" % (user, host))
                    f.write(copycmds)
                    f.write(permissioncmds)
                    if cmds != "":
                        f.write("scp cmds.sh $host:\n")
                        f.write("ssh $host bash cmds.sh")
        return {'result': 'success'}
Beispiel #5
0
 def create(self,
            name,
            virttype=None,
            profile='',
            plan='kvirt',
            flavor=None,
            cpumodel='Westmere',
            cpuflags=[],
            cpupinning=[],
            numcpus=2,
            memory=512,
            guestid='guestrhel764',
            pool='default',
            image=None,
            disks=[{
                'size': 10
            }],
            disksize=10,
            diskthin=True,
            diskinterface='virtio',
            nets=['default'],
            iso=None,
            vnc=False,
            cloudinit=True,
            reserveip=False,
            reservedns=False,
            reservehost=False,
            start=True,
            keys=None,
            cmds=[],
            ips=None,
            netmasks=None,
            gateway=None,
            nested=True,
            dns=None,
            domain=None,
            tunnel=False,
            files=[],
            enableroot=True,
            alias=[],
            overrides={},
            tags=[],
            storemetadata=False,
            sharedfolders=[],
            kernel=None,
            initrd=None,
            cmdline=None,
            placement=[],
            autostart=False,
            cpuhotplug=False,
            memoryhotplug=False,
            numamode=None,
            numa=[],
            pcidevices=[],
            tpm=False,
            rng=False,
            metadata={},
            securitygroups=[]):
     glance = self.glance
     nova = self.nova
     neutron = self.neutron
     try:
         nova.servers.find(name=name)
         return {
             'result': 'failure',
             'reason': "VM %s already exists" % name
         }
     except:
         pass
     allflavors = [f for f in nova.flavors.list()]
     allflavornames = [flavor.name for flavor in allflavors]
     if flavor is None:
         flavors = [
             flavor for flavor in allflavors
             if flavor.ram >= memory and flavor.vcpus >= numcpus
         ]
         flavor = flavors[0] if flavors else nova.flavors.find(
             name="m1.tiny")
         pprint("Using flavor %s" % flavor.name)
     elif flavor not in allflavornames:
         return {
             'result': 'failure',
             'reason': "Flavor %s not found" % flavor
         }
     else:
         flavor = nova.flavors.find(name=flavor)
     nics = []
     need_floating = True
     for net in nets:
         if isinstance(net, str):
             netname = net
         elif isinstance(net, dict) and 'name' in net:
             netname = net['name']
         try:
             net = nova.neutron.find_network(name=netname)
             if net.to_dict()['router:external']:
                 need_floating = False
         except Exception as e:
             error(e)
             return {
                 'result': 'failure',
                 'reason': "Network %s not found" % netname
             }
         nics.append({'net-id': net.id})
     if image is not None:
         glanceimages = [
             img for img in glance.images.list() if img.name == image
         ]
         if glanceimages:
             glanceimage = glanceimages[0]
         else:
             msg = "you don't have image %s" % image
             return {'result': 'failure', 'reason': msg}
     block_dev_mapping = {}
     for index, disk in enumerate(disks):
         imageref = None
         diskname = "%s-disk%s" % (name, index)
         letter = chr(index + ord('a'))
         if isinstance(disk, int):
             disksize = disk
             diskthin = True
         elif isinstance(disk, str) and disk.isdigit():
             disksize = int(disk)
             diskthin = True
         elif isinstance(disk, dict):
             disksize = disk.get('size', '10')
             diskthin = disk.get('thin', True)
         if index == 0 and image is not None:
             if not diskthin:
                 imageref = glanceimage.id
             else:
                 continue
         newvol = self.cinder.volumes.create(name=diskname,
                                             size=disksize,
                                             imageRef=imageref)
         block_dev_mapping['vd%s' % letter] = newvol.id
     key_name = 'kvirt'
     keypairs = [k.name for k in nova.keypairs.list()]
     if key_name not in keypairs:
         homekey = None
         if not os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME'])\
                 and not os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME']):
             print(
                 "neither id_rsa.pub or id_dsa public keys found in your .ssh directory, you might have trouble "
                 "accessing the vm")
         else:
             if os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME']):
                 homekey = open("%s/.ssh/id_rsa.pub" %
                                os.environ['HOME']).read()
             else:
                 homekey = open("%s/.ssh/id_dsa.pub" %
                                os.environ['HOME']).read()
             nova.keypairs.create(key_name, homekey)
     elif keypairs:
         key_name = keypairs[0]
         if key_name != 'kvirt':
             pprint('Using keypair %s' % key_name)
     else:
         error("Couldn't locate or create keypair for use. Leaving...")
         return {'result': 'failure', 'reason': "No usable keypair found"}
     userdata = None
     if cloudinit:
         if image is not None and common.needs_ignition(image):
             version = common.ignition_version(image)
             userdata = common.ignition(name=name,
                                        keys=keys,
                                        cmds=cmds,
                                        nets=nets,
                                        gateway=gateway,
                                        dns=dns,
                                        domain=domain,
                                        reserveip=reserveip,
                                        files=files,
                                        enableroot=enableroot,
                                        overrides=overrides,
                                        version=version,
                                        plan=plan,
                                        image=image)
         else:
             userdata = common.cloudinit(name=name,
                                         keys=keys,
                                         cmds=cmds,
                                         nets=nets,
                                         gateway=gateway,
                                         dns=dns,
                                         domain=domain,
                                         reserveip=reserveip,
                                         files=files,
                                         enableroot=enableroot,
                                         overrides=overrides,
                                         storemetadata=storemetadata)[0]
     meta = {x: metadata[x] for x in metadata if x in METADATA_FIELDS}
     instance = nova.servers.create(name=name,
                                    image=glanceimage,
                                    flavor=flavor,
                                    key_name=key_name,
                                    nics=nics,
                                    meta=meta,
                                    userdata=userdata,
                                    block_device_mapping=block_dev_mapping,
                                    security_groups=securitygroups)
     tenant_id = instance.tenant_id
     if need_floating:
         floating_ips = [
             f['id'] for f in neutron.list_floatingips()['floatingips']
             if f['port_id'] is None
         ]
         if not floating_ips:
             network_id = None
             if self.external_network is not None:
                 networks = [
                     n for n in neutron.list_networks()['networks']
                     if n['router:external']
                     if n['name'] == self.external_network
                 ]
             else:
                 networks = [
                     n for n in neutron.list_networks()['networks']
                     if n['router:external']
                 ]
             if networks:
                 network_id = networks[0]['id']
             if network_id is not None and tenant_id is not None:
                 args = dict(floating_network_id=network_id,
                             tenant_id=tenant_id)
                 floating_ip = neutron.create_floatingip(
                     body={'floatingip': args})
                 floatingip_id = floating_ip['floatingip']['id']
                 floatingip_ip = floating_ip['floatingip'][
                     'floating_ip_address']
                 pprint('Assigning new floating ip %s for this vm' %
                        floatingip_ip)
         else:
             floatingip_id = floating_ips[0]
         fixed_ip = None
         timeout = 0
         while fixed_ip is None:
             pprint("Waiting 5 seconds for vm to get an ip")
             sleep(5)
             timeout += 5
             if timeout >= 240:
                 error("Time out waiting for vm to get an ip")
                 break
             vm = nova.servers.get(instance.id)
             if vm.status.lower() == 'error':
                 msg = "Vm reports error status"
                 return {'result': 'failure', 'reason': msg}
             for key in list(vm.addresses):
                 entry1 = vm.addresses[key]
                 for entry2 in entry1:
                     if entry2['OS-EXT-IPS:type'] == 'fixed':
                         fixed_ip = entry2['addr']
                         break
         if fixed_ip is not None:
             fixedports = [
                 i['id'] for i in neutron.list_ports()['ports']
                 if i['fixed_ips']
                 and i['fixed_ips'][0]['ip_address'] == fixed_ip
             ]
             port_id = fixedports[0]
             neutron.update_floatingip(floatingip_id,
                                       {'floatingip': {
                                           'port_id': port_id
                                       }})
         if not securitygroups:
             default_securitygroups = [
                 s
                 for s in neutron.list_security_groups()['security_groups']
                 if s['name'] == 'default' and s['tenant_id'] == tenant_id
             ]
             if default_securitygroups:
                 securitygroup = default_securitygroups[0]
                 securitygroupid = securitygroup['id']
                 sshrule = {
                     'security_group_rule': {
                         'direction': 'ingress',
                         'security_group_id': securitygroupid,
                         'port_range_min': '22',
                         'port_range_max': '22',
                         'protocol': 'tcp',
                         'remote_group_id': None,
                         'remote_ip_prefix': '0.0.0.0/0'
                     }
                 }
                 icmprule = {
                     'security_group_rule': {
                         'direction': 'ingress',
                         'security_group_id': securitygroupid,
                         'protocol': 'icmp',
                         'remote_group_id': None,
                         'remote_ip_prefix': '0.0.0.0/0'
                     }
                 }
                 try:
                     neutron.create_security_group_rule(sshrule)
                     neutron.create_security_group_rule(icmprule)
                 except:
                     pass
     return {'result': 'success'}
Beispiel #6
0
 def create(self,
            name,
            virttype=None,
            profile='',
            flavor=None,
            plan='kvirt',
            cpumodel='Westmere',
            cpuflags=[],
            cpupinning=[],
            numcpus=2,
            memory=512,
            guestid='guestrhel764',
            pool='default',
            image=None,
            disks=[{
                'size': 10
            }],
            disksize=10,
            diskthin=True,
            diskinterface='virtio',
            nets=['default'],
            iso=None,
            vnc=False,
            cloudinit=True,
            reserveip=False,
            reservedns=False,
            reservehost=False,
            start=True,
            keys=None,
            cmds=[],
            ips=None,
            netmasks=None,
            gateway=None,
            nested=True,
            dns=None,
            domain=None,
            tunnel=False,
            files=[],
            enableroot=True,
            alias=[],
            overrides={},
            tags=[],
            storemetadata=False,
            sharedfolders=[],
            kernel=None,
            initrd=None,
            cmdline=None,
            placement=[],
            autostart=False,
            cpuhotplug=False,
            memoryhotplug=False,
            numamode=None,
            numa=[],
            pcidevices=[],
            tpm=False,
            rng=False,
            metadata={},
            securitygroups=[]):
     conn = self.conn
     if self.exists(name):
         return {
             'result': 'failure',
             'reason': "VM %s already exists" % name
         }
     image = self.__evaluate_image(image)
     keypair = self.keypair
     if image is not None:
         Filters = [{'Name': 'name', 'Values': [image]}]
         images = conn.describe_images(Filters=Filters)
         if not image.startswith(
                 'ami-') and 'Images' in images and images['Images']:
             imageinfo = images['Images'][0]
             imageid = imageinfo['ImageId']
             pprint("Using ami %s" % imageid)
             image = imageinfo['Name']
         else:
             return {
                 'result': 'failure',
                 'reason': 'Invalid image %s' % image
             }
     else:
         return {
             'result': 'failure',
             'reason': 'An image (or amid) is required'
         }
     defaultsubnetid = None
     if flavor is None:
         matching = [
             f for f in staticf if staticf[f]['cpus'] >= numcpus
             and staticf[f]['memory'] >= memory
         ]
         if matching:
             flavor = matching[0]
             pprint("Using instance type %s" % flavor)
         else:
             return {
                 'result': 'failure',
                 'reason':
                 'Couldnt find instance type matching requirements'
             }
     vmtags = [{
         'ResourceType':
         'instance',
         'Tags': [{
             'Key': 'Name',
             'Value': name
         }, {
             'Key': 'hostname',
             'Value': name
         }]
     }]
     for entry in [field for field in metadata if field in METADATA_FIELDS]:
         vmtags[0]['Tags'].append({'Key': entry, 'Value': metadata[entry]})
     if keypair is None:
         keypair = 'kvirt_%s' % self.access_key_id
     keypairs = [
         k for k in conn.describe_key_pairs()['KeyPairs']
         if k['KeyName'] == keypair
     ]
     if not keypairs:
         pprint("Importing your public key as %s" % keypair)
         if not os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME'])\
                 and not os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME'])\
                 and not os.path.exists("%s/.kcli/id_rsa.pub" % os.environ['HOME'])\
                 and not os.path.exists("%s/.kcli/id_dsa.pub" % os.environ['HOME']):
             error("No public key found. Leaving")
             return {'result': 'failure', 'reason': 'No public key found'}
         elif os.path.exists("%s/.ssh/id_rsa.pub" % os.environ['HOME']):
             homekey = open("%s/.ssh/id_rsa.pub" %
                            os.environ['HOME']).read()
         elif os.path.exists("%s/.ssh/id_dsa.pub" % os.environ['HOME']):
             homekey = open("%s/.ssh/id_dsa.pub" %
                            os.environ['HOME']).read()
         elif os.path.exists("%s/.kcli/id_rsa.pub" % os.environ['HOME']):
             homekey = open("%s/.kcli/id_rsa.pub" %
                            os.environ['HOME']).read()
         else:
             homekey = open("%s/.kcli/id_dsa.pub" %
                            os.environ['HOME']).read()
         conn.import_key_pair(KeyName=keypair, PublicKeyMaterial=homekey)
     if cloudinit:
         if image is not None and common.needs_ignition(image):
             version = common.ignition_version(image)
             userdata = common.ignition(name=name,
                                        keys=keys,
                                        cmds=cmds,
                                        nets=nets,
                                        gateway=gateway,
                                        dns=dns,
                                        domain=domain,
                                        reserveip=reserveip,
                                        files=files,
                                        enableroot=enableroot,
                                        overrides=overrides,
                                        version=version,
                                        plan=plan,
                                        image=image)
         else:
             userdata = common.cloudinit(name=name,
                                         keys=keys,
                                         cmds=cmds,
                                         nets=nets,
                                         gateway=gateway,
                                         dns=dns,
                                         domain=domain,
                                         reserveip=reserveip,
                                         files=files,
                                         enableroot=enableroot,
                                         overrides=overrides,
                                         fqdn=True,
                                         storemetadata=storemetadata)[0]
     else:
         userdata = ''
     networkinterfaces = []
     blockdevicemappings = []
     privateips = []
     for index, net in enumerate(nets):
         networkinterface = {
             'DeleteOnTermination': True,
             'Description': "eth%s" % index,
             'DeviceIndex': index,
             'Groups': ['string'],
             'SubnetId': 'string'
         }
         ip = None
         if isinstance(net, str):
             netname = net
             netpublic = True
         elif isinstance(net, dict) and 'name' in net:
             netname = net['name']
             ip = net.get('ip')
             alias = net.get('alias')
             netpublic = net.get('public', True)
         networkinterface[
             'AssociatePublicIpAddress'] = netpublic if index == 0 else False
         if netname == 'default':
             if defaultsubnetid is not None:
                 netname = defaultsubnetid
             else:
                 vpcs = conn.describe_vpcs()
                 vpcid = [
                     vpc['VpcId'] for vpc in vpcs['Vpcs']
                     if vpc['IsDefault']
                 ][0]
                 subnets = conn.describe_subnets()
                 subnetid = [
                     subnet['SubnetId'] for subnet in subnets['Subnets']
                     if subnet['DefaultForAz'] and subnet['VpcId'] == vpcid
                 ][0]
                 netname = subnetid
                 defaultsubnetid = netname
                 pprint("Using subnet %s as default" % defaultsubnetid)
         if ips and len(ips) > index and ips[index] is not None:
             ip = ips[index]
             if index == 0:
                 networkinterface['PrivateIpAddress'] = ip
                 privateip = {'Primary': True, 'PrivateIpAddress': ip}
             else:
                 privateip = {'Primary': False, 'PrivateIpAddress': ip}
             privateips = privateips.append(privateip)
         networkinterface['SubnetId'] = netname
         networkinterfaces.append(networkinterface)
     if len(privateips) > 1:
         networkinterface['PrivateIpAddresses'] = privateips
     for index, disk in enumerate(disks):
         if image is not None and index == 0:
             continue
         letter = chr(index + ord('a'))
         # devicename = '/dev/sd%s1' % letter if index == 0 else '/dev/sd%s' % letter
         devicename = '/dev/xvd%s' % letter
         blockdevicemapping = {
             'DeviceName': devicename,
             'Ebs': {
                 'DeleteOnTermination': True,
                 'VolumeType': 'standard'
             }
         }
         if isinstance(disk, int):
             disksize = disk
         elif isinstance(disk, str) and disk.isdigit():
             disksize = str(disk)
         elif isinstance(disk, dict):
             disksize = disk.get('size', '10')
             blockdevicemapping['Ebs']['VolumeType'] = disk.get(
                 'type', 'standard')
         blockdevicemapping['Ebs']['VolumeSize'] = disksize
         blockdevicemappings.append(blockdevicemapping)
     SecurityGroupIds = []
     for sg in securitygroups:
         sgid = self.get_security_group_id(sg, vpcid)
         if sgid is not None:
             SecurityGroupIds.append(sgid)
     conn.run_instances(ImageId=imageid,
                        MinCount=1,
                        MaxCount=1,
                        InstanceType=flavor,
                        KeyName=keypair,
                        BlockDeviceMappings=blockdevicemappings,
                        UserData=userdata,
                        TagSpecifications=vmtags,
                        SecurityGroupIds=SecurityGroupIds)
     if reservedns and domain is not None:
         # eip = conn.allocate_address(Domain='vpc')
         # vmid = reservation.instances[0].id
         # conn.associate_address(InstanceId=vmid, AllocationId=eip["AllocationId"])
         # self.reserve_dns(name, nets=nets, domain=domain, alias=alias, instanceid=name, ip=eip["PublicIp"])
         self.reserve_dns(name,
                          nets=nets,
                          domain=domain,
                          alias=alias,
                          instanceid=name)
     return {'result': 'success'}
Beispiel #7
0
 def create(self, name, virttype=None, profile='kvirt', flavor=None, plan='kvirt', cpumodel='host-model',
            cpuflags=[], cpupinning=[], numcpus=2, memory=512, guestid='centos7_64Guest', pool='default', image=None,
            disks=[{'size': 10}], disksize=10, diskthin=True, diskinterface='virtio', nets=['default'], iso=None,
            vnc=False, cloudinit=True, reserveip=False, reservedns=False, reservehost=False, start=True, keys=None,
            cmds=[], ips=None, netmasks=None, gateway=None, nested=True, dns=None, domain=None, tunnel=False,
            files=[], enableroot=True, overrides={}, tags=[], storemetadata=False, sharedfolders=[],
            kernel=None, initrd=None, cmdline=None, placement=[], autostart=False, cpuhotplug=False,
            memoryhotplug=False, numamode=None, numa=[], pcidevices=[], tpm=False, rng=False, metadata={},
            securitygroups=[]):
     dc = self.dc
     vmFolder = dc.vmFolder
     distributed = self.distributed
     diskmode = 'persistent'
     default_diskinterface = diskinterface
     default_diskthin = diskthin
     default_disksize = disksize
     default_pool = pool
     memory = int(memory)
     numcpus = int(numcpus)
     si = self.si
     dc = self.dc
     rootFolder = self.rootFolder
     if plan != 'kvirt':
         createfolder(si, dc.vmFolder, plan)
         vmfolder = find(si, dc.vmFolder, vim.Folder, plan)
     else:
         vmfolder = dc.vmFolder
     si = self.si
     clu = find(si, rootFolder, vim.ComputeResource, self.clu)
     resourcepool = clu.resourcePool
     if image is not None:
         rootFolder = self.rootFolder
         imageobj = findvm(si, rootFolder, image)
         if imageobj is None:
             return {'result': 'failure', 'reason': "Image %s not found" % image}
         clonespec = createclonespec(resourcepool)
         confspec = vim.vm.ConfigSpec()
         confspec.annotation = name
         confspec.memoryMB = memory
         confspec.numCPUs = numcpus
         planopt = vim.option.OptionValue()
         planopt.key = 'plan'
         planopt.value = plan
         profileopt = vim.option.OptionValue()
         profileopt.key = 'profile'
         profileopt.value = profile
         imageopt = vim.option.OptionValue()
         imageopt.key = 'image'
         imageopt.value = image
         extraconfig = [imageopt, planopt, profileopt]
         clonespec.config = confspec
         clonespec.powerOn = False
         cloudinitiso = None
         if cloudinit:
             if image is not None and common.needs_ignition(image):
                 version = common.ignition_version(image)
                 ignitiondata = common.ignition(name=name, keys=keys, cmds=cmds, nets=nets, gateway=gateway, dns=dns,
                                                domain=domain, reserveip=reserveip, files=files,
                                                enableroot=enableroot, overrides=overrides, version=version,
                                                plan=plan, image=image)
                 ignitionopt = vim.option.OptionValue()
                 ignitionopt.key = 'guestinfo.ignition.config.data'
                 ignitionopt.value = base64.b64encode(ignitiondata.encode()).decode()
                 encodingopt = vim.option.OptionValue()
                 encodingopt.key = 'guestinfo.ignition.config.data.encoding'
                 encodingopt.value = 'base64'
                 extraconfig.extend([ignitionopt, encodingopt])
             else:
                 # customspec = makecuspec(name, nets=nets, gateway=gateway, dns=dns, domain=domain)
                 # clonespec.customization = customspec
                 cloudinitiso = "[%s]/%s/%s.ISO" % (default_pool, name, name)
                 userdata, metadata, netdata = common.cloudinit(name=name, keys=keys, cmds=cmds, nets=nets,
                                                                gateway=gateway, dns=dns, domain=domain,
                                                                reserveip=reserveip, files=files,
                                                                enableroot=enableroot, overrides=overrides,
                                                                storemetadata=storemetadata)
         confspec.extraConfig = extraconfig
         t = imageobj.CloneVM_Task(folder=vmfolder, name=name, spec=clonespec)
         waitForMe(t)
         if cloudinitiso is not None:
             with TemporaryDirectory() as tmpdir:
                 common.make_iso(name, tmpdir, userdata, metadata, netdata)
                 cloudinitisofile = "%s/%s.ISO" % (tmpdir, name)
                 self._uploadimage(default_pool, cloudinitisofile, name)
             vm = findvm(si, vmFolder, name)
             c = changecd(self.si, vm, cloudinitiso)
             waitForMe(c)
     datastores = {}
     confspec = vim.vm.ConfigSpec()
     confspec.name = name
     confspec.annotation = name
     confspec.memoryMB = memory
     confspec.numCPUs = numcpus
     confspec.extraConfig = []
     for entry in [field for field in metadata if field in METADATA_FIELDS]:
         opt = vim.option.OptionValue()
         opt.key = entry
         opt.value = metadata[entry]
         confspec.extraConfig.append(opt)
     if nested:
         confspec.nestedHVEnabled = True
     confspec.guestId = 'centos7_64Guest'
     vmfi = vim.vm.FileInfo()
     filename = "[" + default_pool + "]"
     vmfi.vmPathName = filename
     confspec.files = vmfi
     if vnc:
         vncport = random.randint(5900, 7000)
         opt1 = vim.option.OptionValue()
         opt1.key = 'RemoteDisplay.vnc.port'
         opt1.value = vncport
         opt2 = vim.option.OptionValue()
         opt2.key = 'RemoteDisplay.vnc.enabled'
         opt2.value = "TRUE"
         confspec.extraConfig = [opt1, opt2]
     if image is None:
         t = vmfolder.CreateVM_Task(confspec, resourcepool)
         waitForMe(t)
     vm = find(si, dc.vmFolder, vim.VirtualMachine, name)
     currentdevices = vm.config.hardware.device
     currentdisks = [d for d in currentdevices if isinstance(d, vim.vm.device.VirtualDisk)]
     currentnics = [d for d in currentdevices if isinstance(d, vim.vm.device.VirtualEthernetCard)]
     confspec = vim.vm.ConfigSpec()
     devconfspec = []
     for index, disk in enumerate(disks):
         if disk is None:
             disksize = default_disksize
             diskthin = default_diskthin
             diskinterface = default_diskinterface
             diskpool = default_pool
         elif isinstance(disk, int):
             disksize = disk
             diskthin = default_diskthin
             diskinterface = default_diskinterface
             diskpool = default_pool
         elif isinstance(disk, str) and disk.isdigit():
             disksize = int(disk)
             diskthin = default_diskthin
             diskinterface = default_diskinterface
             diskpool = default_pool
         elif isinstance(disk, dict):
             disksize = disk.get('size', default_disksize)
             diskthin = disk.get('thin', default_diskthin)
             diskinterface = disk.get('interface', default_diskinterface)
             diskpool = disk.get('pool', default_pool)
         if index < len(currentdisks) and image is not None:
             currentdisk = currentdisks[index]
             currentsize = convert(1000 * currentdisk.capacityInKB, GB=False)
             if int(currentsize) < disksize:
                 pprint("Waiting for image disk %s to be resized" % index)
                 currentdisk.capacityInKB = disksize * 1048576
                 diskspec = vim.vm.ConfigSpec()
                 diskspec = vim.vm.device.VirtualDeviceSpec(device=currentdisk, operation="edit")
                 devconfspec.append(diskspec)
             continue
         disksize = disksize * 1048576
         if diskpool not in datastores:
             datastore = find(si, rootFolder, vim.Datastore, diskpool)
             if not datastore:
                 return {'result': 'failure', 'reason': "Pool %s not found" % diskpool}
             else:
                 datastores[diskpool] = datastore
         if index == 0:
             scsispec = createscsispec()
             devconfspec.append(scsispec)
         diskspec = creatediskspec(index, disksize, datastore, diskmode, diskthin)
         devconfspec.append(diskspec)
     # NICSPEC
     for index, net in enumerate(nets):
         if index < len(currentnics):
             continue
         nicname = 'Network Adapter %d' % (index + 1)
         if net == 'default':
             net = 'VM Network'
         nicspec = createnicspec(nicname, net)
         devconfspec.append(nicspec)
     if iso:
         if '/' not in iso:
             matchingisos = [i for i in self._getisos() if i.endswith(iso)]
             if matchingisos:
                 iso = matchingisos[0]
             else:
                 return {'result': 'failure', 'reason': "Iso %s not found" % iso}
         cdspec = createisospec(iso)
         devconfspec.append(cdspec)
         # bootoptions = vim.option.OptionValue(key='bios.bootDeviceClasses',value='allow:hd,cd,fd,net')
         # confspec.bootOptions = vim.vm.BootOptions(bootOrder=[vim.vm.BootOptions.BootableCdromDevice()])
     confspec.deviceChange = devconfspec
     t = vm.Reconfigure(confspec)
     waitForMe(t)
     # HANDLE DVS
     if distributed:
         # 2-GETMAC
         vm = findvm(si, vmfolder, name)
         if vm is None:
             return "%s not found" % (name)
         devices = vm.config.hardware.device
         macaddr = []
         for dev in devices:
             if "addressType" in dir(dev):
                 macaddr.append(dev.macAddress)
         portgs = {}
         o = si.content.viewManager.CreateContainerView(rootFolder, [vim.DistributedVirtualSwitch], True)
         dvnetworks = o.view
         o.Destroy()
         for dvnetw in dvnetworks:
             uuid = dvnetw.uuid
             for portg in dvnetw.portgroup:
                 portgs[portg.name] = [uuid, portg.key]
         for k in range(len(nets)):
             net = nets[k]
             mactochange = macaddr[k]
             if net in portgs.keys():
                 confspec = vim.vm.VirtualMachineSpec()
                 nicspec = vim.vm.device.VirtualDeviceSpec()
                 nicspec.operation = vim.ConfigSpecOperation.edit
                 nic = vim.vm.device.VirtualPCNet32()
                 dnicbacking = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
                 dvconnection = vim.dvs.DistributedVirtualSwitchPortConnection()
                 dvconnection.switchUuid = portgs[net][0]
                 dvconnection.portgroupKey = portgs[net][1]
                 dnicbacking.port = dvconnection
                 nic.backing = dnicbacking
                 nicspec.device = nic
                 # 2-GETMAC
                 vm = findvm(si, vmfolder, name)
                 if vm is None:
                     return "%s not found" % (name)
                 devices = vm.config.hardware.device
                 for dev in devices:
                     if "addressType" in dir(dev):
                         mac = dev.macAddress
                         if mac == mactochange:
                             dev.backing = dnicbacking
                             nicspec.device = dev
                             devconfspec = [nicspec]
                             confspec.deviceChange = devconfspec
                             t = vm.reconfigVM_Task(confspec)
                             waitForMe(t)
                             t = vm.PowerOnVM_Task(None)
                             waitForMe(t)
     if start:
         t = vm.PowerOnVM_Task(None)
         waitForMe(t)
     return {'result': 'success'}
Beispiel #8
0
    def create(self, name, virttype='kvm', profile='', flavor=None, plan='kvirt', cpumodel='Westmere', cpuflags=[],
               numcpus=2, memory=512, guestid='guestrhel764', pool='default', template=None, disks=[{'size': 10}],
               disksize=10, diskthin=True, diskinterface='virtio', nets=['default'], iso=None, vnc=False,
               cloudinit=True, reserveip=False, reservedns=False, reservehost=False, start=True, keys=None, cmds=[],
               ips=None, netmasks=None, gateway=None, nested=True, dns=None, domain=None, tunnel=False, files=[],
               enableroot=True, alias=[], overrides={}, tags={}):
        """

        :param name:
        :param virttype:
        :param profile:
        :param flavor:
        :param plan:
        :param cpumodel:
        :param cpuflags:
        :param numcpus:
        :param memory:
        :param guestid:
        :param pool:
        :param template:
        :param disks:
        :param disksize:
        :param diskthin:
        :param diskinterface:
        :param nets:
        :param iso:
        :param vnc:
        :param cloudinit:
        :param reserveip:
        :param reservedns:
        :param reservehost:
        :param start:
        :param keys:
        :param cmds:
        :param ips:
        :param netmasks:
        :param gateway:
        :param nested:
        :param dns:
        :param domain:
        :param tunnel:
        :param files:
        :param enableroot:
        :param alias:
        :param overrides:
        :param tags:
        :return:
        """
        conn = self.conn
        project = self.project
        zone = self.zone
        region = self.region
        if flavor is None:
            if numcpus != 1 and numcpus % 2 != 0:
                return {'result': 'failure', 'reason': "Number of cpus is not even"}
            if memory != 512 and memory % 1024 != 0:
                return {'result': 'failure', 'reason': "Memory is not multiple of 1024"}
            if numcpus > 1 and memory < 2048:
                common.pprint("Rounding memory to 2048Mb as more than one cpu is used", color='blue')
                memory = 2048
            machine_type = 'custom-%s-%s' % (numcpus, memory)
            if memory < 921.6:
                common.pprint("Rounding memory to 1024Mb", color='blue')
                machine_type = 'f1-micro'
        else:
            machine_type = flavor
        machine_type = "zones/%s/machineTypes/%s" % (zone, machine_type)
        body = {'name': name, 'machineType': machine_type, 'networkInterfaces': []}
        foundnets = []
        for index, net in enumerate(nets):
            ip = None
            if isinstance(net, str):
                netname = net
            elif isinstance(net, dict) and 'name' in net:
                netname = net['name']
                if 'ip' in net:
                    ip = net['ip']
                if 'alias' in net:
                    alias = net['alias']
            if ips and len(ips) > index and ips[index] is not None:
                ip = ips[index]
            if netname in foundnets:
                continue
            else:
                foundnets.append(netname)
            newnet = {'network': 'global/networks/%s' % netname}
            if netname == 'default':
                newnet['accessConfigs'] = [{'type': 'ONE_TO_ONE_NAT', 'name': 'External NAT'}]
            else:
                newnet['subnetwork'] = 'projects/%s/regions/%s/subnetworks/%s' % (project, region, netname)
            if ip is not None:
                newnet['networkIP'] = ip
            body['networkInterfaces'].append(newnet)
        body['disks'] = []
        for index, disk in enumerate(disks):
            if isinstance(disk, int):
                disksize = disk
            elif isinstance(disk, str) and disk.isdigit():
                disksize = int(disk)
            elif isinstance(disk, dict):
                disksize = disk.get('size', '10')
            newdisk = {'boot': False, 'autoDelete': True}
            if index == 0 and template is not None:
                template = self.__evaluate_template(template)
                templateproject = self.__get_template_project(template)
                if templateproject is not None:
                    image_response = conn.images().getFromFamily(project=templateproject, family=template).execute()
                else:
                    try:
                        image_response = conn.images().get(project=self.project, image=template).execute()
                    except:
                        return {'result': 'failure', 'reason': 'Issue with template %s' % template}
                src = image_response['selfLink']
                newdisk['initializeParams'] = {'sourceImage': src, 'diskSizeGb': disksize}
                newdisk['boot'] = True
            else:
                diskname = "%s-disk%s" % (name, index)
                diskpath = '/compute/v1/projects/%s/zones/%s/disks/%s' % (project, zone, diskname)
                info = {'sizeGb': disksize, 'sourceDisk': 'zones/%s/diskTypes/pd-standard' % zone, 'name': diskname}
                conn.disks().insert(zone=zone, project=project, body=info).execute()
                timeout = 0
                while True:
                    if timeout > 60:
                        return {'result': 'failure', 'reason': 'timeout waiting for disk %s to be ready' % diskname}
                    newstatus = conn.disks().get(zone=zone, project=project, disk=diskname).execute()
                    if newstatus['status'] == 'READY':
                        break
                    else:
                        timeout += 5
                        time.sleep(5)
                        common.pprint("Waiting for disk %s to be ready" % diskname, color='green')
                newdisk['source'] = diskpath
            body['disks'].append(newdisk)
        body['serviceAccounts'] = [{'email': 'default',
                                    'scopes': ['https://www.googleapis.com/auth/devstorage.read_write',
                                               'https://www.googleapis.com/auth/logging.write']}]
        body['metadata'] = {'items': []}
        startup_script = ''
        for fil in files:
            if not isinstance(fil, dict):
                continue
            origin = fil.get('origin')
            path = fil.get('path')
            content = fil.get('content')
            if origin is not None:
                origin = os.path.expanduser(origin)
                if not os.path.exists(origin):
                    print("Skipping file %s as not found" % origin)
                    continue
                binary = True if '.' in origin and origin.split('.')[-1].lower() in binary_types else False
                if binary:
                    with open(origin, "rb") as f:
                        content = f.read().encode("base64")
                elif overrides:
                    basedir = os.path.dirname(origin) if os.path.dirname(origin) != '' else '.'
                    env = Environment(block_start_string='[%', block_end_string='%]',
                                      variable_start_string='[[', variable_end_string=']]',
                                      loader=FileSystemLoader(basedir))
                    templ = env.get_template(os.path.basename(origin))
                    newfile = templ.render(overrides)
                    startup_script += "cat <<'EOF' >%s\n%s\nEOF\n" % (path, newfile)
                else:
                    newfile = open(origin, 'r').read()
                    startup_script += "cat <<'EOF' >%s\n%s\nEOF\n" % (path, newfile)
            elif content is None:
                continue
        if cmds:
            for cmd in cmds:
                if cmd.startswith('#'):
                    continue
                else:
                    newcmd = Environment(block_start_string='[%', block_end_string='%]',
                                         variable_start_string='[[',
                                         variable_end_string=']]').from_string(cmd).render(overrides)
                startup_script += '%s\n' % newcmd
        if startup_script != '':
            beginningcmd = 'test -f /root/.kcli_startup && exit 0\n'
            endcmd = 'touch /root/.kcli_startup\n'
            newval = {'key': 'startup-script', 'value': beginningcmd + startup_script + endcmd}
            body['metadata']['items'].append(newval)
        if not os.path.exists(os.path.expanduser("~/.ssh/id_rsa.pub"))\
                and not os.path.exists(os.path.expanduser("~/.ssh/id_dsa.pub"))\
                and not os.path.exists(os.path.expanduser("~/.kcli/id_rsa.pub"))\
                and not os.path.exists(os.path.expanduser("~/.kcli/id_dsa.pub")):
            print("neither id_rsa.pub or id_dsa public keys found in your .ssh or .kcli directory, you might have "
                  "trouble accessing the vm")
            homekey = None
        elif os.path.exists(os.path.expanduser("~/.ssh/id_rsa.pub")):
            homekey = open(os.path.expanduser("~/.ssh/id_rsa.pub")).read()
        elif os.path.exists(os.path.expanduser("~/.ssh/id_dsa.pub")):
            homekey = open(os.path.expanduser("~/.ssh/id_dsa.pub")).read()
        elif os.path.exists(os.path.expanduser("~/.kcli/id_rsa.pub")):
            homekey = open(os.path.expanduser("~/.kcli/id_rsa.pub")).read()
        else:
            homekey = open(os.path.expanduser("~/.kcli/id_dsa.pub")).read()
        if homekey is not None:
            keys = [homekey] + keys if keys is not None else [homekey]
        if keys is not None:
            keys = ["%s: %s" % (self.user, x) for x in keys]
            keys = ''.join(keys)
            newval = {'key': 'ssh-keys', 'value': keys}
            body['metadata']['items'].append(newval)
        newval = {'key': 'plan', 'value': plan}
        body['metadata']['items'].append(newval)
        newval = {'key': 'profile', 'value': profile}
        body['metadata']['items'].append(newval)
        if tags:
            body['tags'] = {'items': tags}
        if reservedns:
            newval = {'key': 'domain', 'value': domain}
            body['metadata']['items'].append(newval)
        if template is not None and (template.startswith('coreos') or template.startswith('rhcos')):
            etcd = None
            userdata = common.ignition(name=name, keys=keys, cmds=cmds, nets=nets, gateway=gateway, dns=dns,
                                       domain=domain, reserveip=reserveip, files=files, enableroot=enableroot,
                                       overrides=overrides, etcd=etcd)
            newval = {'key': 'user-data', 'value': userdata}
            body['metadata']['items'].append(newval)
        if self.debug:
            print(body)
        conn.instances().insert(project=project, zone=zone, body=body).execute()
        if reservedns:
            self.reserve_dns(name, nets=nets, domain=domain, alias=alias)
        return {'result': 'success'}