def create(self, num, os_type, os_version, arch, resources_hint): """ Create num OpenStack instances running os_type os_version and return their names. Each instance has at least the resources described in resources_hint. """ log.debug('ProvisionOpenStack:create') resources_hint = self.interpret_hints({ 'machine': config['openstack']['machine'], 'volumes': config['openstack']['volumes'], }, resources_hint) self.init_user_data(os_type, os_version) image = self.image(os_type, os_version) if 'network' in config['openstack']: net = "--nic net-id=" + str(self.net_id(config['openstack']['network'])) else: net = '' flavor = self.flavor(resources_hint['machine'], config['openstack'].get('flavor-select-regexp')) misc.sh("flock --close /tmp/teuthology-server-create.lock openstack server create" + " " + config['openstack'].get('server-create', '') + " -f json " + " --image '" + str(image) + "'" + " --flavor '" + str(flavor) + "'" + " --key-name teuthology " + " --user-data " + str(self.user_data) + " " + net + " --min " + str(num) + " --max " + str(num) + " --security-group teuthology" + " --property teuthology=" + self.property + " --property ownedby=" + config.openstack['ip'] + " --wait " + " " + self.basename) instances = filter( lambda instance: self.property in instance['Properties'], self.list_instances()) instances = [OpenStackInstance(i['ID'], i) for i in instances] fqdns = [] try: network = config['openstack'].get('network', '') for instance in instances: name = self.ip2name(self.basename, instance.get_ip(network)) misc.sh("openstack server set " + "--name " + name + " " + instance['ID']) fqdn = name + '.' + config.lab_domain if not misc.ssh_keyscan_wait(fqdn): raise ValueError('ssh_keyscan_wait failed for ' + fqdn) time.sleep(15) if not self.cloud_init_wait(fqdn): raise ValueError('clound_init_wait failed for ' + fqdn) self.attach_volumes(name, resources_hint['volumes']) fqdns.append(fqdn) except Exception as e: log.exception(str(e)) for id in [instance['ID'] for instance in instances]: self.destroy(id) raise e return fqdns
def create(self, num, os_type, os_version, arch, resources_hint): """ Create num OpenStack instances running os_type os_version and return their names. Each instance has at least the resources described in resources_hint. """ log.debug('ProvisionOpenStack:create') resources_hint = self.interpret_hints( { 'machine': config['openstack']['machine'], 'volumes': config['openstack']['volumes'], }, resources_hint) self.init_user_data(os_type, os_version) image = self.image(os_type, os_version) if 'network' in config['openstack']: net = "--nic net-id=" + str( self.net_id(config['openstack']['network'])) else: net = '' flavor = self.flavor(resources_hint['machine'], config['openstack'].get('flavor-select-regexp')) misc.sh( "flock --close /tmp/teuthology-server-create.lock openstack server create" + " " + config['openstack'].get('server-create', '') + " -f json " + " --image '" + str(image) + "'" + " --flavor '" + str(flavor) + "'" + " --key-name teuthology " + " --user-data " + str(self.user_data) + " " + net + " --min " + str(num) + " --max " + str(num) + " --security-group teuthology" + " --property teuthology=" + self.property + " --property ownedby=" + config.openstack['ip'] + " --wait " + " " + self.basename) all_instances = json.loads( misc.sh("openstack server list -f json --long")) instances = filter( lambda instance: self.property in instance['Properties'], all_instances) fqdns = [] try: network = config['openstack'].get('network', '') for instance in instances: name = self.ip2name(self.basename, self.get_ip(instance['ID'], network)) misc.sh("openstack server set " + "--name " + name + " " + instance['ID']) fqdn = name + '.' + config.lab_domain if not misc.ssh_keyscan_wait(fqdn): raise ValueError('ssh_keyscan_wait failed for ' + fqdn) import time time.sleep(15) if not self.cloud_init_wait(fqdn): raise ValueError('clound_init_wait failed for ' + fqdn) self.attach_volumes(name, resources_hint['volumes']) fqdns.append(fqdn) except Exception as e: log.exception(str(e)) for id in [instance['ID'] for instance in instances]: self.destroy(id) raise e return fqdns
def destroy(self, name_or_id): """ Delete the name_or_id OpenStack instance. """ log.debug('ProvisionOpenStack:destroy ' + name_or_id) if not self.exists(name_or_id): return True volumes = self.list_volumes(name_or_id) misc.sh("openstack server delete --wait " + name_or_id) for volume in volumes: misc.sh("openstack volume delete " + volume) return True
def attach_volumes(self, name, volumes): """ Create and attach volumes to the named OpenStack instance. """ for i in range(volumes['count']): volume_name = name + '-' + str(i) try: misc.sh("openstack volume show -f json " + volume_name) except subprocess.CalledProcessError as e: if 'No volume with a name or ID' not in e.output: raise e misc.sh("openstack volume create -f json " + config['openstack'].get('volume-create', '') + " " + " --property ownedby=" + config.openstack['ip'] + " --size " + str(volumes['size']) + " " + volume_name) with safe_while(sleep=2, tries=100, action="volume " + volume_name) as proceed: while proceed(): r = misc.sh("openstack volume show -f json " + volume_name) status = self.get_value(json.loads(r), 'status') if status == 'available': break else: log.info("volume " + volume_name + " not available yet") misc.sh("openstack server add volume " + name + " " + volume_name)
def attach_volumes(self, name, volumes): """ Create and attach volumes to the named OpenStack instance. """ for i in range(volumes["count"]): volume_name = name + "-" + str(i) try: misc.sh("openstack volume show -f json " + volume_name) except subprocess.CalledProcessError as e: if "No volume with a name or ID" not in e.output: raise e misc.sh( "openstack volume create -f json " + config["openstack"].get("volume-create", "") + " " + " --property ownedby=" + config.openstack["ip"] + " --size " + str(volumes["size"]) + " " + volume_name ) with safe_while(sleep=2, tries=100, action="volume " + volume_name) as proceed: while proceed(): r = misc.sh("openstack volume show -f json " + volume_name) status = self.get_value(json.loads(r), "status") if status == "available": break else: log.info("volume " + volume_name + " not available yet") misc.sh("openstack server add volume " + name + " " + volume_name)
def attach_volumes(self, name, hint): """ Create and attach volumes to the named OpenStack instance. """ if hint: volumes = hint['volumes'] else: volumes = config['openstack']['volumes'] for i in range(volumes['count']): volume_name = name + '-' + str(i) try: misc.sh("openstack volume show -f json " + volume_name) except subprocess.CalledProcessError as e: if 'No volume with a name or ID' not in e.output: raise e misc.sh("openstack volume create -f json " + config['openstack'].get('volume-create', '') + " " + " --size " + str(volumes['size']) + " " + volume_name) with safe_while(sleep=2, tries=100, action="volume " + volume_name) as proceed: while proceed(): r = misc.sh("openstack volume show -f json " + volume_name) status = self.get_value(json.loads(r), 'status') if status == 'available': break else: log.info("volume " + volume_name + " not available yet") misc.sh("openstack server add volume " + name + " " + volume_name)
def list_volumes(self, name_or_id): """ Return the uuid of the volumes attached to the name_or_id OpenStack instance. """ instance = misc.sh("openstack server show -f json " + name_or_id) volumes = self.get_value(json.loads(instance), 'os-extended-volumes:volumes_attached') return [ volume['id'] for volume in volumes ]
def destroy(self, name_or_id): """ Delete the name_or_id OpenStack instance. """ log.debug("ProvisionOpenStack:destroy " + name_or_id) server_info = self.show(name_or_id) if not self.exists(name_or_id, server_info=server_info): return True volumes = self.list_volumes(name_or_id, server_info=server_info) server_id = self.get_value(server_info, "ID") misc.sh("openstack server set --name REMOVE-ME-" + name_or_id + " " + server_id) misc.sh("openstack server delete --wait " + server_id + " || true") for volume in volumes: misc.sh("openstack volume set --name REMOVE-ME " + volume) misc.sh("openstack volume delete " + volume + " || true") return True
def destroy(self, name_or_id): """ Delete the name_or_id OpenStack instance. """ log.debug('ProvisionOpenStack:destroy ' + name_or_id) server_info = self.show(name_or_id) if not self.exists(name_or_id, server_info=server_info): return True volumes = self.list_volumes(name_or_id, server_info=server_info) server_id = self.get_value(server_info, 'ID') misc.sh("openstack server set --name REMOVE-ME-" + name_or_id + " " + server_id) misc.sh("openstack server delete --wait " + server_id + " || true") for volume in volumes: misc.sh("openstack volume set --name REMOVE-ME " + volume) misc.sh("openstack volume delete " + volume + " || true") return True
def destroy(self, name_or_id): """ Delete the name_or_id OpenStack instance. """ log.debug('ProvisionOpenStack:destroy ' + name_or_id) server_info = self.show(name_or_id) if not self.exists(name_or_id, server_info=server_info): return True volumes = self.list_volumes(name_or_id, server_info=server_info) if self.get_value(server_info, 'status').lower() == 'error': log.info( "Instance %s is in an error state; skipping volume detachment", name_or_id ) else: for volume in volumes: misc.sh("openstack server remove volume %s %s" % (name_or_id, volume)) misc.sh("openstack server delete " + name_or_id) for volume in volumes: misc.sh("openstack volume delete " + volume) return True
def create(self, num, os_type, os_version, arch, resources_hint): """ Create num OpenStack instances running os_type os_version and return their names. Each instance has at least the resources described in resources_hint. """ log.debug("ProvisionOpenStack:create") resources_hint = self.interpret_hints( {"machine": config["openstack"]["machine"], "volumes": config["openstack"]["volumes"]}, resources_hint ) self.init_user_data(os_type, os_version) image = self.image(os_type, os_version) if "network" in config["openstack"]: net = "--nic net-id=" + str(self.net_id(config["openstack"]["network"])) else: net = "" flavor = self.flavor(resources_hint["machine"], config["openstack"].get("flavor-select-regexp")) misc.sh( "flock --close /tmp/teuthology-server-create.lock openstack server create" + " " + config["openstack"].get("server-create", "") + " -f json " + " --image '" + str(image) + "'" + " --flavor '" + str(flavor) + "'" + " --key-name teuthology " + " --user-data " + str(self.user_data) + " " + net + " --min " + str(num) + " --max " + str(num) + " --security-group teuthology" + " --property teuthology=" + self.property + " --property ownedby=" + config.openstack["ip"] + " --wait " + " " + self.basename ) all_instances = json.loads(misc.sh("openstack server list -f json --long")) instances = filter(lambda instance: self.property in instance["Properties"], all_instances) fqdns = [] try: network = config["openstack"].get("network", "") for instance in instances: name = self.ip2name(self.basename, self.get_ip(instance["ID"], network)) misc.sh("openstack server set " + "--name " + name + " " + instance["ID"]) fqdn = name + "." + config.lab_domain if not misc.ssh_keyscan_wait(fqdn): raise ValueError("ssh_keyscan_wait failed for " + fqdn) import time time.sleep(15) if not self.cloud_init_wait(fqdn): raise ValueError("clound_init_wait failed for " + fqdn) self.attach_volumes(name, resources_hint["volumes"]) fqdns.append(fqdn) except Exception as e: log.exception(str(e)) for id in [instance["ID"] for instance in instances]: self.destroy(id) raise e return fqdns