def __init__(self, ipAddr, port, verbose): ''' Constructor: takes IP address and port of the ViPR instance. These are needed to make http requests for REST API ''' self.__ipAddr = ipAddr self.__port = port self._host = Host(self.__ipAddr, self.__port) self._hostinitiator = HostInitiator(self.__ipAddr, self.__port) self._network = Network(self.__ipAddr, self.__port) self._execute = utils.execute self._vipr_info = ViPRInfo(self.VIPR_CONFIG_FILE) self.set_logging(verbose)
class Openstack(object): ''' The class definition for operations related to 'Openstack'. ''' #Commonly used URIs for the 'Openstack' module URI_HOST_SEARCH = '/compute/hosts/search?name={0}' URI_HOST_BULK = '/compute/hosts/bulk' URI_NETWORK_BULK = '/vdc/networks/bulk' URI_NETWORK_PORTS = '/vdc/networks/{0}/storage-ports' URI_STORAGEPORT_ALL = '/vdc/storage-ports' URI_STORAGEPORT_BULK = '/vdc/storage-ports/bulk' VIPR_CONFIG_FILE = '/etc/cinder/cinder.conf' def __init__(self, ipAddr, port, verbose): ''' Constructor: takes IP address and port of the ViPR instance. These are needed to make http requests for REST API ''' self.__ipAddr = ipAddr self.__port = port self._host = Host(self.__ipAddr, self.__port) self._hostinitiator = HostInitiator(self.__ipAddr, self.__port) self._network = Network(self.__ipAddr, self.__port) self._execute = utils.execute self._vipr_info = ViPRInfo(self.VIPR_CONFIG_FILE) self.set_logging(verbose) def set_logging(self, verbose): self._logger = logging.getLogger(__name__) if (verbose): self._logger.setLevel(logging.DEBUG) else: self._logger.setLevel(logging.INFO) logging.basicConfig(format='%(asctime)s:%(levelname)s: %(message)s') def get_logger(self): return self._logger def get_hostname(self, hostname = None): if (not hostname): return socket.getfqdn() else: return hostname def get_vipr_info(self): return self._vipr_info #@retry_wrapper def add_host(self, host_param, connector, vipr_param): self._vipr_info.authenticate_user() varray = vipr_param['varray'] # Find or create host. host = self.create_host(host_param['hostname'], vipr_param['tenant'], vipr_param['project']) self._logger.info('Created/found host %s', host['name']) self._logger.debug('Details of host %s: %s', host_param['hostname'], host) # Find or create initiator. initiator = self.create_initiator(host, connector) self._logger.info('Added initiator %s to host %s', initiator['initiator_port'], host['name']) self._logger.debug('Details of initiator %s', initiator) # Find network network = self.find_iscsi_network(vipr_param['varray'], vipr_param['network']) if (network): self._logger.info('Found network %s in virtual array %s', network['name'], varray) else: self._logger('Cannot find a network in virtual array %s to place the initiator', varray) exit(1) # add initiator to network if (initiator['initiator_port'] not in network['endpoints']): self.add_initiator_to_network(host, initiator, network, vipr_param['varray']) self._logger.info('Added initiator %s to network %s', initiator['initiator_port'], network['name']) self._logger.debug('Network details %s: ', network) @vipr_retry_wrapper def create_host(self, hostname, tenant, project, ostype='Linux'): # find host host = self.find_host(hostname) if (not host): if (not ostype) : ostype = "Linux" # host not found, create a new one. task_rep = self._host.create(hostname, ostype, hostname, tenant, None, None, None, None, None, None, None, None, None) host = common.show_by_href(self.__ipAddr, self.__port, task_rep['resource']) return host ''' Find host by name of host object in ViPR, normally the hostname of the host. Parameters: name: name of the host Returns: host details in JSON ''' def find_host(self, hostname): shortname = hostname[:hostname.find(".")] (s, h) = common.service_json_request(self.__ipAddr, self.__port, "GET", self.URI_HOST_SEARCH.format(shortname), None) o = common.json_decode(s); ids = [] for host in o['resource'] : ids.append(host['id']) body = json.dumps({'id' : ids}) (s, h) = common.service_json_request(self.__ipAddr, self.__port, "POST", self.URI_HOST_BULK, body) o = common.json_decode(s) for host in o['host']: if (host['inactive']): continue if (hostname in host['host_name'] or host['host_name'] in hostname ): return host def get_localhost_initiator(self, protocol='iSCSI'): if (protocol == 'iSCSI'): wwpn = libvirt_utils.get_iscsi_initiator() initiator = {'wwpn' : wwpn} return initiator def find_initiator(self, host, wwpn): initiators = self._host.list_initiators(host) for initiator in initiators: if (initiator['name'] == wwpn): return initiator return None def create_initiator(self, host, connector): initiator = self.find_initiator(host['name'], connector['wwpn']) if (not initiator): initiator = self._hostinitiator.create(host['name'], 'iSCSI', None, connector['wwpn']) return common.show_by_href(self.__ipAddr, self.__port, initiator) ''' Find network for a given network name. If network name is not specified ''' def find_iscsi_network(self, varray, network_name): if (network_name): try: return self._network.network_query(network_name, varray) except SOSError: # TODO: re-raise the exception with correct name. To be removed raise SOSError(SOSError.NOT_FOUND_ERR, "Network {0} not found".format(network_name)) storage_ports = self.get_varray_iscsi_storageports(varray) for port in storage_ports: port_info = dict() port_info['native_guid'] = port['native_guid'] port_info['port_name'] = port['port_name'] try: ip_address = port['ip_address'] port_info['ip_address'] = ip_address if (self.is_ip_pingable(ip_address)): network = port['network'] network_detail = common.show_by_href(self.__ipAddr, self.__port, network) port_info['network'] = network_detail['name'] self._logger.debug('Select storage port %s: ', port_info) return network_detail else: self._logger.debug('Skip storage port %s: ', port_info) except KeyError: self._logger.debug('Skip storage port %s: ', port_info) continue def is_ip_pingable(self, ip_address): self._logger.debug('ping ip address %s ', ip_address) try: (out, err) = self._execute('ping', '-c', '2', ip_address) self._logger.debug(out) return True except Exception as ex: return False def get_ip_networks(self, varray): networks = self._network.list_networks(varray) ip_networks = [] resources = self.get_bulk_details(networks, self.URI_NETWORK_BULK) for x in resources['network']: if (x['transport_type'] == 'IP'): ip_networks.append(x) return ip_networks def get_bulk_details(self, resources, bulkuri): ids = [] for each in resources : ids.append(each['id']) body = json.dumps({'id' : ids}) (s, h) = common.service_json_request(self.__ipAddr, self.__port, "POST", bulkuri, body) return common.json_decode(s) ''' Attach host initiators to a network Parameters: name: name of the host network: name of the network to be attached Return: network details in JSON ''' def add_initiator_to_network(self, host, initiator, network, varray): if (network['transport_type'] == 'IP' and initiator['protocol'] == 'iSCSI'): return self._network.add_endpoint(varray, network['name'], initiator['initiator_port']) def get_varray_iscsi_storageports(self, varray): iscsi_ports = [] for port in self.get_varray_storageports(varray): if (port['transport_type'] != 'IP'): continue if ('iqn' not in port['port_network_id']): continue if ('Not Available' in port['ip_address'] ): continue iscsi_ports.append(port) return iscsi_ports """ Get all storage ports Returns: Storage ports in JSON """ def get_varray_storageports(self, varray): networks = self._network.list_networks(varray) ids = [] for net in networks: net_id = net['id'] (s, h) = common.service_json_request(self.__ipAddr, self.__port, "GET", self.URI_NETWORK_PORTS.format(net_id) , None) o = common.json_decode(s) for port in o['storage_port']: ids.append(port['id']) body = json.dumps({'id' : ids}) (s, h) = common.service_json_request(self.__ipAddr, self.__port, "POST", self.URI_STORAGEPORT_BULK, body) o = common.json_decode(s) return o['storage_port'] def log_info(self, message): import datetime timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") sys.stdout.write(timestamp + ': ' + message + '\n')