def create_export(self, context, volume, connector): d_res_name, d_vol_nr = self._resource_name_volnr_for_volume(volume) nodename = connector["host"] # Ensure the node is known to DRBDmanage. # Note that this does *not* mean that DRBDmanage has to # be installed on it! # This is just so that DRBD allows the IP to connect. node_prop = { dm_const.NODE_ADDR: connector["ip"], dm_const.FLAG_DRBDCTRL: dm_const.BOOL_FALSE, dm_const.FLAG_STORAGE: dm_const.BOOL_FALSE, dm_const.FLAG_EXTERNAL: dm_const.BOOL_TRUE, } res = self.call_or_reconnect( self.odm.create_node, nodename, node_prop) self._check_result(res, ignore=[dm_exc.DM_EEXIST]) # Ensure the data is accessible, by creating an assignment. assg_prop = { dm_const.FLAG_DISKLESS: dm_const.BOOL_TRUE, } # If we create the assignment here, it's temporary - # and has to be removed later on again. assg_prop.update(dm_utils.aux_props_to_dict({ AUX_PROP_TEMP_CLIENT: dm_const.BOOL_TRUE, })) res = self.call_or_reconnect( self.odm.assign, nodename, d_res_name, assg_prop) self._check_result(res, ignore=[dm_exc.DM_EEXIST]) # Wait for DRBDmanage to have completed that action. # A DRBDmanage controlled node will set the cstate:deploy flag; # an external node will not be available to change it, so we have # to wait for the storage nodes to remove the upd_con flag # (ie. they're now ready to receive the connection). if self._is_external_node(nodename): self._wait_for_node_assignment( d_res_name, d_vol_nr, [], check_vol_deployed=False, filter_props={ # must be deployed CS_DEPLOYED: dm_const.BOOL_TRUE, # must be a storage node (not diskless), CS_DISKLESS: dm_const.BOOL_FALSE, # connection must be available, no need for updating CS_UPD_CON: dm_const.BOOL_FALSE, }) else: self._wait_for_node_assignment( d_res_name, d_vol_nr, [nodename], check_vol_deployed=True, filter_props={ CS_DEPLOYED: dm_const.BOOL_TRUE, }) return self._return_connection_data(nodename, volume)