You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/01/25 03:37:22 UTC
[1/2] generalize storage orchestration: DataObjectManager will handle
all the object life cycle management
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index f3da368..8cfbae4 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -22,7 +22,8 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
@@ -31,6 +32,7 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
+import org.apache.cloudstack.storage.datastore.DataObjectManager;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
@@ -55,6 +57,8 @@ public class VolumeServiceImpl implements VolumeService {
@Inject
ObjectInDataStoreManager objectInDataStoreMgr;
@Inject
+ DataObjectManager dataObjectMgr;
+ @Inject
ImageMotionService imageMotion;
@Inject
TemplateInstallStrategy templateInstallStrategy;
@@ -85,6 +89,8 @@ public class VolumeServiceImpl implements VolumeService {
}
+
+
@Override
public AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, long dataStoreId) {
PrimaryDataStore dataStore = dataStoreMgr.getPrimaryDataStore(dataStoreId);
@@ -107,16 +113,16 @@ public class VolumeServiceImpl implements VolumeService {
vo.stateTransit(Volume.Event.CreateRequested);
CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, vo, future);
- AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
+ AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createVolumeCallback(null, null))
.setContext(context);
- //dataStore.createVolumeAsync(vo, null, caller);
+ dataObjectMgr.createAsync(volume, dataStore, caller, true);
return future;
}
- protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> callback, CreateVolumeContext<VolumeApiResult> context) {
- CommandResult result = callback.getResult();
+ protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
+ CreateCmdResult result = callback.getResult();
VolumeObject vo = context.getVolume();
VolumeApiResult volResult = new VolumeApiResult(vo);
if (result.isSuccess()) {
@@ -172,7 +178,7 @@ public class VolumeServiceImpl implements VolumeService {
caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null))
.setContext(context);
- dataStore.getDriver().deleteAsync(volume, caller);
+ dataObjectMgr.deleteAsync(volume, caller);
return future;
}
@@ -279,21 +285,23 @@ public class VolumeServiceImpl implements VolumeService {
@DB
protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) {
- CreateBaseImageContext<VolumeApiResult> context = new CreateBaseImageContext<VolumeApiResult>(null, volume,
+ CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume,
dataStore,
template,
future);
- AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> caller = AsyncCallbackDispatcher.create(this);
- caller.setCallback(caller.getTarget().createBaseImageCallback(null, null))
+ AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
+ caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null))
.setContext(context);
-
- templateInstallStrategy.installAsync(template, dataStore, caller);
+ DataObject templateOnPrimaryStoreObj = dataObjectMgr.createInternalStateOnly(template, dataStore);
+
+ dataObjectMgr.copyAsync(context.srcTemplate, templateOnPrimaryStoreObj, caller);
+ return;
}
-
+
@DB
- protected Void createBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
- CreateBaseImageResult result = callback.getResult();
+ protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
+ CreateCmdResult result = callback.getResult();
VolumeApiResult res = new VolumeApiResult(context.getVolume());
AsyncCallFuture<VolumeApiResult> future = context.getFuture();
@@ -302,23 +310,26 @@ public class VolumeServiceImpl implements VolumeService {
future.complete(res);
return null;
}
-
- //now create volume on base image
- TemplateInfo templateOnPrimaryStoreObj = result.template;
- VolumeInfo volume = context.getVolume();
- PrimaryDataStore pd = context.getDataStore();
+ DataObject templateOnPrimaryStoreObj = objectInDataStoreMgr.get(context.srcTemplate, context.dataStore);
- createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, future);
+ createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future);
return null;
}
private class CreateVolumeFromBaseImageContext<T> extends AsyncRpcConext<T> {
private final VolumeObject vo;
private final AsyncCallFuture<VolumeApiResult> future;
- public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo, AsyncCallFuture<VolumeApiResult> future) {
+ private final DataStore primaryStore;
+ private final DataObject templateOnStore;
+ public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo,
+ DataStore primaryStore,
+ DataObject templateOnStore,
+ AsyncCallFuture<VolumeApiResult> future) {
super(callback);
this.vo = vo;
this.future = future;
+ this.primaryStore = primaryStore;
+ this.templateOnStore = templateOnStore;
}
public VolumeObject getVolumeObject() {
@@ -331,7 +342,7 @@ public class VolumeServiceImpl implements VolumeService {
}
@DB
- protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) {
+ protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) {
VolumeObject vo = (VolumeObject) volume;
try {
vo.stateTransit(Volume.Event.CreateRequested);
@@ -342,19 +353,22 @@ public class VolumeServiceImpl implements VolumeService {
return;
}
- CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, future);
- AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
- caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallback(null, null))
+ CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, pd, templateOnPrimaryStore, future);
+ AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
+ caller.setCallback(caller.getTarget().copyBaseImageCallBack(null, null))
.setContext(context);
- pd.getDriver().copyAsync(volume, templateOnPrimaryStore, caller);
+ DataObject volumeOnPrimaryStorage = dataObjectMgr.createInternalStateOnly(volume, pd);
+ dataObjectMgr.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller);
+ return;
}
@DB
- public Object createVolumeFromBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
+ public Void copyBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
VolumeObject vo = context.getVolumeObject();
- CopyCommandResult result = callback.getResult();
+ CreateCmdResult result = callback.getResult();
VolumeApiResult volResult = new VolumeApiResult(vo);
+
if (result.isSuccess()) {
if (result.getPath() != null) {
vo.setPath(result.getPath());
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
index 1aa96c3..06367af 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
@@ -28,22 +28,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.UUID;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
import org.apache.cloudstack.storage.command.CopyCmd;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.command.CreateObjectCommand;
import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
-import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO;
-import org.apache.cloudstack.storage.to.NfsPrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.TemplateTO;
import org.apache.cloudstack.storage.to.VolumeTO;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -57,8 +53,10 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
-import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.storage.encoding.DataStore;
+import com.cloud.utils.storage.encoding.DecodedDataObject;
+import com.cloud.utils.storage.encoding.Decoder;
import com.xensource.xenapi.Connection;
import com.xensource.xenapi.Host;
import com.xensource.xenapi.PBD;
@@ -137,28 +135,23 @@ public class XenServerStorageResource {
}
protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
String uriString = cmd.getObjectUri();
- Map<String, String> params = null;
-
- try {
- URI uri = new URI(uriString);
- params = getParameters(uri);
- } catch (URISyntaxException e1) {
- s_logger.debug("uri exception", e1);
- return new CreateObjectAnswer(cmd, false, e1.toString());
- }
-
- if (params.get("objType").equalsIgnoreCase("template")) {
- return getTemplateSize(cmd, params.get("path"));
- }
-
- long size = Long.parseLong(params.get("size"));
- String name = params.get("name");
- String storeUuid = params.get("storagePath");
+ DecodedDataObject obj = null;
+
Connection conn = hypervisorResource.getConnection();
VDI vdi = null;
boolean result = false;
String errorMsg = null;
+
try {
+ obj = Decoder.decode(uriString);
+ DataStore store = obj.getStore();
+ if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image")) {
+ return getTemplateSize(cmd, obj.getPath());
+ }
+
+ long size = obj.getSize();
+ String name = obj.getName();
+ String storeUuid = store.getUuid();
SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid);
vdi = createVdi(conn, name, primaryDataStoreSR, size);
VDI.Record record = vdi.getRecord(conn);
@@ -173,6 +166,9 @@ public class XenServerStorageResource {
} catch (XmlRpcException e) {
s_logger.debug("Failed to create volume", e);
errorMsg = e.toString();
+ } catch (URISyntaxException e) {
+ s_logger.debug("Failed to create volume", e);
+ errorMsg = e.toString();
} finally {
if (!result && vdi != null) {
try {
@@ -227,13 +223,13 @@ public class XenServerStorageResource {
}
}
- protected SR getNfsSR(Connection conn, URI uri) {
+ protected SR getNfsSR(Connection conn, DataStore store) {
Map<String, String> deviceConfig = new HashMap<String, String>();
- Map<String, String> params = getParameters(uri);
- String uuid = params.get("storeUuid");
+
+ String uuid = store.getUuid();
try {
- String server = uri.getHost();
- String serverpath = uri.getPath();
+ String server = store.getServer();
+ String serverpath = store.getPath();
serverpath = serverpath.replace("//", "/");
Set<SR> srs = SR.getAll(conn);
@@ -410,25 +406,17 @@ public class XenServerStorageResource {
protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
Connection conn = hypervisorResource.getConnection();
String storeUrl = cmd.getDataStore();
- String scheme = null;
- String type = null;
- URI storeUri = null;
- try {
- storeUri = new URI(storeUrl);
- } catch(URISyntaxException e) {
- return new Answer(cmd, false, e.toString());
- }
-
- scheme = storeUri.getScheme();
-
+
try {
- if (scheme.equalsIgnoreCase("nfs")) {
- SR sr = getNfsSR(conn, storeUri);
- } else if (scheme.equalsIgnoreCase("iscsi")) {
+ DecodedDataObject obj = Decoder.decode(storeUrl);
+ DataStore store = obj.getStore();
+ if (store.getScheme().equalsIgnoreCase("nfs")) {
+ SR sr = getNfsSR(conn, store);
+ } else if (store.getScheme().equalsIgnoreCase("iscsi")) {
//getIscsiSR(conn, dataStore);
- } else if (scheme.equalsIgnoreCase("presetup")) {
+ } else if (store.getScheme().equalsIgnoreCase("presetup")) {
} else {
- return new Answer(cmd, false, "The pool type: " + scheme + " is not supported.");
+ return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported.");
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
@@ -509,31 +497,30 @@ public class XenServerStorageResource {
}
- protected Answer directDownloadHttpTemplate(CopyCmd cmd, TemplateTO template, PrimaryDataStoreTO primarDataStore) {
- String primaryStoreUuid = primarDataStore.getUuid();
+ protected Answer directDownloadHttpTemplate(CopyCmd cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
Connection conn = hypervisorResource.getConnection();
SR poolsr = null;
VDI vdi = null;
boolean result = false;
try {
-
- Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid);
+ if (destObj.getPath() == null) {
+ //need to create volume at first
+
+ }
+ vdi = VDI.getByUuid(conn, destObj.getPath());
+ if (vdi == null) {
+ throw new CloudRuntimeException("can't find volume: " + destObj.getPath());
+ }
+ String destStoreUuid = destObj.getStore().getUuid();
+ Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid);
if (srs.size() != 1) {
- throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique");
+ throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique");
}
poolsr = srs.iterator().next();
- VDI.Record vdir = new VDI.Record();
- vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString();
- vdir.SR = poolsr;
- vdir.type = Types.VdiType.USER;
-
- vdir.virtualSize = getTemplateSize(conn, template.getPath());
- vdi = VDI.create(conn, vdir);
-
- vdir = vdi.getRecord(conn);
+ VDI.Record vdir = vdi.getRecord(conn);
String vdiLocation = vdir.location;
String pbdLocation = null;
- if (primarDataStore.getType().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
+ if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn);
} else {
Set<PBD> pbds = poolsr.getPBDs(conn);
@@ -551,7 +538,7 @@ public class XenServerStorageResource {
String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
//download a url into vdipath
//downloadHttpToLocalFile(vdiPath, template.getPath());
- hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath());
+ hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath());
result = true;
return new CopyCmdAnswer(cmd, vdi.getUuid(conn));
} catch (BadServerResponse e) {
@@ -581,16 +568,10 @@ public class XenServerStorageResource {
protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
String dataStoreUri = cmd.getDataStore();
Connection conn = hypervisorResource.getConnection();
- Map<String, String> params = null;
try {
- try {
- URI uri = new URI(dataStoreUri);
- params = getParameters(uri);
- } catch (URISyntaxException e1) {
- s_logger.debug("uri exception", e1);
- return new CreateObjectAnswer(cmd, false, e1.toString());
- }
- SR sr = hypervisorResource.getStorageRepository(conn, params.get("storeUuid"));
+ DecodedDataObject obj = Decoder.decode(dataStoreUri);
+ DataStore store = obj.getStore();
+ SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid());
hypervisorResource.setupHeartbeatSr(conn, sr, false);
long capacity = sr.getPhysicalSize(conn);
long available = capacity - sr.getPhysicalUtilisation(conn);
@@ -616,10 +597,18 @@ public class XenServerStorageResource {
}
protected Answer execute(CopyCmd cmd) {
- ImageOnPrimayDataStoreTO imageTO = cmd.getImage();
- TemplateTO template = imageTO.getTemplate();
- if (template.getPath().startsWith("http")) {
- return directDownloadHttpTemplate(cmd, template, imageTO.getPrimaryDataStore());
+ DecodedDataObject srcObj = null;
+ DecodedDataObject destObj = null;
+ try {
+ srcObj = Decoder.decode(cmd.getSrcUri());
+ destObj = Decoder.decode(cmd.getDestUri());
+ } catch (URISyntaxException e) {
+ return new Answer(cmd, false, e.toString());
+ }
+
+
+ if (srcObj.getPath().startsWith("http")) {
+ return directDownloadHttpTemplate(cmd, srcObj, destObj);
} else {
return new Answer(cmd, false, "not implemented yet");
/*
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
index e066dff..04b553c 100644
--- a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
@@ -37,7 +37,7 @@ public class VMTemplateDetailsDaoImpl extends GenericDaoBase<VMTemplateDetailVO,
protected final SearchBuilder<VMTemplateDetailVO> TemplateSearch;
protected final SearchBuilder<VMTemplateDetailVO> DetailSearch;
- protected VMTemplateDetailsDaoImpl() {
+ public VMTemplateDetailsDaoImpl() {
TemplateSearch = createSearchBuilder();
TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
TemplateSearch.done();
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/setup/db/4.1-new-db-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/4.1-new-db-schema.sql b/setup/db/4.1-new-db-schema.sql
index d541537..e8bafa2 100644
--- a/setup/db/4.1-new-db-schema.sql
+++ b/setup/db/4.1-new-db-schema.sql
@@ -18,6 +18,8 @@
alter table vm_template add image_data_store_id bigint unsigned;
alter table vm_template add size bigint unsigned;
alter table vm_template add state varchar(255);
+alter table vm_template add update_count bigint unsigned;
+alter table vm_template add updated datetime;
alter table storage_pool add storage_provider_id bigint unsigned;
alter table storage_pool add scope varchar(255);
alter table storage_pool modify id bigint unsigned AUTO_INCREMENT UNIQUE NOT NULL;
@@ -67,7 +69,7 @@ CREATE TABLE `cloud`.`object_datastore_ref` (
`size` bigint unsigned COMMENT 'the size of the template on the pool',
`state` varchar(255) NOT NULL,
`update_count` bigint unsigned NOT NULL,
- `updated` DATETIME NOT NULL,
+ `updated` DATETIME,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;