CLOUDSTACK-240: added id/uuid fields to remote_access_vpn table and corresponding VO/Dao objects. The DB upgrade is covered as well. Now tags can be created for the VPN object
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e00f22df Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e00f22df Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e00f22df Branch: refs/heads/qemu-img Commit: e00f22df8a3c93f2fe64c1b61f66c1d703ee1a47 Parents: 6092721 Author: Alena Prokharchyk <alena.prokharc...@citrix.com> Authored: Fri Mar 29 10:36:55 2013 -0700 Committer: Alena Prokharchyk <alena.prokharc...@citrix.com> Committed: Fri Mar 29 10:40:28 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/network/RemoteAccessVpn.java | 4 +- .../cloud/network/vpn/RemoteAccessVpnService.java | 2 +- api/src/com/cloud/server/ResourceTag.java | 3 +- api/src/org/apache/cloudstack/api/BaseCmd.java | 1 - .../command/user/vpn/DeleteRemoteAccessVpnCmd.java | 2 +- .../api/response/RemoteAccessVpnResponse.java | 7 +++ server/src/com/cloud/api/ApiResponseHelper.java | 1 + .../com/cloud/network/dao/RemoteAccessVpnVO.java | 29 +++++++++- .../router/VirtualNetworkApplianceManagerImpl.java | 4 +- .../network/vpn/RemoteAccessVpnManagerImpl.java | 30 ++++++---- .../com/cloud/tags/TaggedResourceManagerImpl.java | 8 +--- .../src/com/cloud/upgrade/dao/Upgrade410to420.java | 41 +++++++++++++- setup/db/db/schema-410to420-cleanup.sql | 7 +++ setup/db/db/schema-410to420.sql | 3 + 14 files changed, 109 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/com/cloud/network/RemoteAccessVpn.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/RemoteAccessVpn.java b/api/src/com/cloud/network/RemoteAccessVpn.java index 1b46330..058b2f4 100644 --- a/api/src/com/cloud/network/RemoteAccessVpn.java +++ b/api/src/com/cloud/network/RemoteAccessVpn.java @@ -17,8 +17,10 @@ package com.cloud.network; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; -public interface RemoteAccessVpn extends ControlledEntity { +public interface RemoteAccessVpn extends ControlledEntity, InternalIdentity, Identity { enum State { Added, Running, http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index bfd2c89..d637da6 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -45,6 +45,6 @@ public interface RemoteAccessVpnService { List<? extends RemoteAccessVpn> listRemoteAccessVpns(long networkId); - RemoteAccessVpn getRemoteAccessVpn(long vpnId); + RemoteAccessVpn getRemoteAccessVpn(long vpnAddrId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/com/cloud/server/ResourceTag.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/server/ResourceTag.java b/api/src/com/cloud/server/ResourceTag.java index ee56748..9006e30 100644 --- a/api/src/com/cloud/server/ResourceTag.java +++ b/api/src/com/cloud/server/ResourceTag.java @@ -38,7 +38,8 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit Vpc, NetworkACL, StaticRoute, - VMSnapshot + VMSnapshot, + RemoteAccessVpn } /** http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/org/apache/cloudstack/api/BaseCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 8b7f43f..7ccb72e 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -28,7 +28,6 @@ import java.util.regex.Pattern; import javax.inject.Inject; import org.apache.cloudstack.query.QueryService; -import org.apache.cloudstack.region.RegionService; import org.apache.cloudstack.usage.UsageService; import org.apache.log4j.Logger; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index 7ddd795..5b1c5c6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -63,7 +63,7 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { if (ownerId == null) { - RemoteAccessVpn vpnEntity = _entityMgr.findById(RemoteAccessVpn.class, publicIpId); + RemoteAccessVpn vpnEntity = _ravService.getRemoteAccessVpn(publicIpId); if(vpnEntity != null) return vpnEntity.getAccountId(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/api/src/org/apache/cloudstack/api/response/RemoteAccessVpnResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/RemoteAccessVpnResponse.java b/api/src/org/apache/cloudstack/api/response/RemoteAccessVpnResponse.java index 7db5663..5e08bca 100644 --- a/api/src/org/apache/cloudstack/api/response/RemoteAccessVpnResponse.java +++ b/api/src/org/apache/cloudstack/api/response/RemoteAccessVpnResponse.java @@ -57,6 +57,9 @@ public class RemoteAccessVpnResponse extends BaseResponse implements ControlledE @SerializedName(ApiConstants.STATE) @Param(description="the state of the rule") private String state; + + @SerializedName(ApiConstants.ID) @Param(description="the id of the remote access vpn") + private String id; public void setPublicIp(String publicIp) { this.publicIp = publicIp; @@ -100,5 +103,9 @@ public class RemoteAccessVpnResponse extends BaseResponse implements ControlledE public void setProjectName(String projectName) { this.projectName = projectName; } + + public void setId(String id) { + this.id = id; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/api/ApiResponseHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index ec80909..d350de2 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1191,6 +1191,7 @@ public class ApiResponseHelper implements ResponseGenerator { populateOwner(vpnResponse, vpn); vpnResponse.setState(vpn.getState().toString()); + vpnResponse.setId(vpn.getUuid()); vpnResponse.setObjectName("remoteaccessvpn"); return vpnResponse; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/network/dao/RemoteAccessVpnVO.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/dao/RemoteAccessVpnVO.java b/server/src/com/cloud/network/dao/RemoteAccessVpnVO.java index 478decf..2e8ee91 100644 --- a/server/src/com/cloud/network/dao/RemoteAccessVpnVO.java +++ b/server/src/com/cloud/network/dao/RemoteAccessVpnVO.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.network.dao; +import java.util.UUID; + import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.RemoteAccessVpn.State; @Entity @Table(name=("remote_access_vpn")) @@ -36,7 +39,6 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { @Column(name="domain_id") private long domainId; - @Id @Column(name="vpn_server_addr_id") private long serverAddressId; @@ -51,8 +53,18 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { @Column(name="state") private State state; + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; - public RemoteAccessVpnVO() { } + public RemoteAccessVpnVO() { + this.uuid = UUID.randomUUID().toString(); + } public RemoteAccessVpnVO(long accountId, long domainId, long networkId, long publicIpId, String localIp, String ipRange, String presharedKey) { this.accountId = accountId; @@ -63,6 +75,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { this.domainId = domainId; this.networkId = networkId; this.state = State.Added; + this.uuid = UUID.randomUUID().toString(); } @Override @@ -116,4 +129,14 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { public long getNetworkId() { return networkId; } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return uuid; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 78168b0..67c94fc 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -303,8 +303,6 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject VpnUserDao _vpnUsersDao; @Inject - RemoteAccessVpnDao _remoteAccessVpnDao; - @Inject RulesManager _rulesMgr; @Inject NetworkDao _networkDao; @@ -2346,7 +2344,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.Vpn, provider)) { - RemoteAccessVpn vpn = _vpnDao.findById(ip.getId()); + RemoteAccessVpn vpn = _vpnDao.findByPublicIpAddress(ip.getId()); if (vpn != null) { vpns.add(vpn); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index d64a021..673535a 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -108,6 +108,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc SearchBuilder<RemoteAccessVpnVO> VpnSearch; @Override + @DB public RemoteAccessVpn createRemoteAccessVpn(long publicIpId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException { UserContext ctx = UserContext.current(); @@ -183,10 +184,17 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc long startIp = NetUtils.ip2Long(range[0]); String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1]; String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength); + + Transaction txn = Transaction.currentTxn(); + txn.start(); + _rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); vpnVO = new RemoteAccessVpnVO(ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(), publicIpId, range[0], newIpRange, sharedSecret); - return _remoteAccessVpnDao.persist(vpnVO); + RemoteAccessVpn vpn = _remoteAccessVpnDao.persist(vpnVO); + + txn.commit(); + return vpn; } private void validateRemoteAccessVpnConfiguration() throws ConfigurationException { @@ -217,7 +225,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc @Override @DB public void destroyRemoteAccessVpn(long ipId, Account caller) throws ResourceUnavailableException { - RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(ipId); + RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { s_logger.debug("vpn id=" + ipId + " does not exists "); return; @@ -228,7 +236,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc Network network = _networkMgr.getNetwork(vpn.getNetworkId()); vpn.setState(RemoteAccessVpn.State.Removed); - _remoteAccessVpnDao.update(vpn.getServerAddressId(), vpn); + _remoteAccessVpnDao.update(vpn.getId(), vpn); boolean success = false; @@ -273,7 +281,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc if (success) { try { txn.start(); - _remoteAccessVpnDao.remove(ipId); + _remoteAccessVpnDao.remove(vpn.getId()); // Stop billing of VPN users when VPN is removed. VPN_User_ADD events will be generated when VPN is created again List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); for(VpnUserVO user : vpnUsers){ @@ -363,18 +371,16 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } @Override @DB - public RemoteAccessVpnVO startRemoteAccessVpn(long vpnId, boolean openFirewall) throws ResourceUnavailableException { + public RemoteAccessVpnVO startRemoteAccessVpn(long ipAddressId, boolean openFirewall) throws ResourceUnavailableException { Account caller = UserContext.current().getCaller(); - RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findById(vpnId); + RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipAddressId); if (vpn == null) { - throw new InvalidParameterValueException("Unable to find your vpn: " + vpnId); + throw new InvalidParameterValueException("Unable to find your vpn: " + ipAddressId); } _accountMgr.checkAccess(caller, null, true, vpn); - - Network network = _networkMgr.getNetwork(vpn.getNetworkId()); boolean started = false; @@ -399,7 +405,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc Transaction txn = Transaction.currentTxn(); txn.start(); vpn.setState(RemoteAccessVpn.State.Running); - _remoteAccessVpnDao.update(vpn.getServerAddressId(), vpn); + _remoteAccessVpnDao.update(vpn.getId(), vpn); // Start billing of existing VPN users in ADD and Active state List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); @@ -607,8 +613,8 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } @Override - public RemoteAccessVpn getRemoteAccessVpn(long vpnId) { - return _remoteAccessVpnDao.findById(vpnId); + public RemoteAccessVpn getRemoteAccessVpn(long vpnAddrId) { + return _remoteAccessVpnDao.findByPublicIpAddress(vpnAddrId); } public List<RemoteAccessVPNServiceProvider> getRemoteAccessVPNServiceProviders() { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/tags/TaggedResourceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java index 06756b6..20fccee 100644 --- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java +++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java @@ -25,13 +25,10 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; - import com.cloud.api.query.dao.ResourceTagJoinDao; -import com.cloud.api.query.vo.ResourceTagJoinVO; import com.cloud.domain.Domain; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -46,7 +43,6 @@ import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.security.dao.SecurityGroupDao; import com.cloud.network.vpc.dao.StaticRouteDao; import com.cloud.network.vpc.dao.VpcDao; -import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.dao.ProjectDao; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; @@ -60,12 +56,9 @@ import com.cloud.user.AccountManager; import com.cloud.user.DomainManager; import com.cloud.user.UserContext; import com.cloud.utils.Pair; -import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.DbUtil; -import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -143,6 +136,7 @@ public class TaggedResourceManagerImpl extends ManagerBase implements TaggedReso _daoMap.put(TaggedResourceType.NetworkACL, _firewallDao); _daoMap.put(TaggedResourceType.StaticRoute, _staticRouteDao); _daoMap.put(TaggedResourceType.VMSnapshot, _vmSnapshotDao); + _daoMap.put(TaggedResourceType.RemoteAccessVpn, _vpnDao); return true; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/server/src/com/cloud/upgrade/dao/Upgrade410to420.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java index f210dc1..d26da4d 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -17,9 +17,6 @@ package com.cloud.upgrade.dao; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; - import java.io.File; import java.sql.Connection; import java.sql.PreparedStatement; @@ -29,6 +26,9 @@ import java.util.UUID; import org.apache.log4j.Logger; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + public class Upgrade410to420 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade410to420.class); @@ -61,6 +61,7 @@ public class Upgrade410to420 implements DbUpgrade { public void performDataMigration(Connection conn) { upgradeVmwareLabels(conn); createPlaceHolderNics(conn); + updateRemoteAccessVpn(conn); PreparedStatement sql = null; try { sql = conn.prepareStatement("update vm_template set image_data_store_id = 1 where type = 'SYSTEM' or type = 'BUILTIN'"); @@ -196,4 +197,38 @@ public class Upgrade410to420 implements DbUpgrade { } } } + + + private void updateRemoteAccessVpn(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("SELECT vpn_server_addr_id FROM `cloud`.`remote_access_vpn`"); + rs = pstmt.executeQuery(); + long id=1; + while (rs.next()) { + String uuid = UUID.randomUUID().toString(); + Long ipId = rs.getLong(1); + pstmt = conn.prepareStatement("UPDATE `cloud`.`remote_access_vpn` set uuid=?, id=? where vpn_server_addr_id=?"); + pstmt.setString(1, uuid); + pstmt.setLong(2, id); + pstmt.setLong(3, ipId); + pstmt.executeUpdate(); + id++; + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to update id/uuid of remote_access_vpn table", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/setup/db/db/schema-410to420-cleanup.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-410to420-cleanup.sql b/setup/db/db/schema-410to420-cleanup.sql index 51970b2..187076f 100644 --- a/setup/db/db/schema-410to420-cleanup.sql +++ b/setup/db/db/schema-410to420-cleanup.sql @@ -19,3 +19,10 @@ -- Schema cleanup from 4.1.0 to 4.2.0; --; +#have to drop the foreign key in order to delete primary key; will re-insert the foreign key later +ALTER TABLE remote_access_vpn DROP foreign key `fk_remote_access_vpn__vpn_server_addr_id`; +ALTER TABLE remote_access_vpn DROP primary key; +ALTER TABLE remote_access_vpn ADD primary key (`id`); +ALTER TABLE remote_access_vpn ADD CONSTRAINT `fk_remote_access_vpn__vpn_server_addr_id` FOREIGN KEY (`vpn_server_addr_id`) REFERENCES `user_ip_address` (`id`); + + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e00f22df/setup/db/db/schema-410to420.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index f1e24fa..53f3c44 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -390,3 +390,6 @@ CREATE VIEW `cloud`.`account_view` AS `cloud`.`async_job` ON async_job.instance_id = account.id and async_job.instance_type = 'Account' and async_job.job_status = 0; + +ALTER TABLE remote_access_vpn ADD COLUMN `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id'; +ALTER TABLE remote_access_vpn ADD COLUMN `uuid` varchar(40) UNIQUE;