Merge branch '4.19'

This commit is contained in:
nvazquez 2024-03-14 22:46:48 -03:00
commit db564b12b6
No known key found for this signature in database
GPG Key ID: 656E1BCC8CB54F84
23 changed files with 388 additions and 42 deletions

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
import org.apache.cloudstack.quota.QuotaTariff;
import org.apache.cloudstack.usage.Usage;
import org.apache.cloudstack.vm.schedule.VMSchedule;
@ -729,6 +730,11 @@ public class EventTypes {
public static final String EVENT_BUCKET_DELETE = "BUCKET.DELETE";
public static final String EVENT_BUCKET_UPDATE = "BUCKET.UPDATE";
// Quota
public static final String EVENT_QUOTA_TARIFF_CREATE = "QUOTA.TARIFF.CREATE";
public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE";
public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE";
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@ -1178,6 +1184,11 @@ public class EventTypes {
entityEventDetails.put(EVENT_BUCKET_CREATE, Bucket.class);
entityEventDetails.put(EVENT_BUCKET_UPDATE, Bucket.class);
entityEventDetails.put(EVENT_BUCKET_DELETE, Bucket.class);
// Quota
entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class);
entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class);
}
public static String getEntityForEvent(String eventName) {

View File

@ -80,7 +80,8 @@ public enum ApiCommandResourceType {
VpnCustomerGateway(com.cloud.network.Site2SiteCustomerGateway.class),
ManagementServer(org.apache.cloudstack.management.ManagementServerHost.class),
ObjectStore(org.apache.cloudstack.storage.object.ObjectStore.class),
Bucket(org.apache.cloudstack.storage.object.Bucket.class);
Bucket(org.apache.cloudstack.storage.object.Bucket.class),
QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class);
private final Class<?> clazz;

View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface QuotaTariff extends InternalIdentity, Identity {
}

View File

@ -131,7 +131,7 @@ public class SecurityGroupVMMapDaoImpl extends GenericDaoBase<SecurityGroupVMMap
SearchCriteria<SecurityGroupVMMapVO> sc = ListBySecurityGroupAndStates.create();
sc.setParameters("securityGroupId", securityGroupId);
sc.setParameters("states", (Object[])vmStates);
return listBy(sc, null, true);
return listBy(sc, null);
}
@Override

View File

@ -0,0 +1,66 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.upgrade.dao;
import com.cloud.utils.exception.CloudRuntimeException;
import java.io.InputStream;
import java.sql.Connection;
public class Upgrade41900to41910 implements DbUpgrade {
@Override
public String[] getUpgradableVersionRange() {
return new String[] {"4.19.0.0", "4.19.1.0"};
}
@Override
public String getUpgradedVersion() {
return "4.19.1.0";
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
@Override
public InputStream[] getPrepareScripts() {
final String scriptFile = "META-INF/db/schema-41900to41910.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
@Override
public void performDataMigration(Connection conn) {
}
@Override
public InputStream[] getCleanupScripts() {
final String scriptFile = "META-INF/db/schema-41900to41910-cleanup.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
}

View File

@ -0,0 +1,20 @@
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--;
-- Schema upgrade cleanup from 4.19.0.0 to 4.19.1.0
--;

View File

@ -0,0 +1,32 @@
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--;
-- Schema upgrade from 4.19.0.0 to 4.19.1.0
--;
-- Updates the populated Quota tariff's types VM_DISK_BYTES_READ, VM_DISK_BYTES_WRITE, VM_DISK_IO_READ and VM_DISK_IO_WRITE to the correct unit.
UPDATE cloud_usage.quota_tariff
SET usage_unit = 'Bytes', updated_on = NOW()
WHERE effective_on = '2010-05-04 00:00:00'
AND name IN ('VM_DISK_BYTES_READ', 'VM_DISK_BYTES_WRITE');
UPDATE cloud_usage.quota_tariff
SET usage_unit = 'IOPS', updated_on = NOW()
WHERE effective_on = '2010-05-04 00:00:00'
AND name IN ('VM_DISK_IO_READ', 'VM_DISK_IO_WRITE');

View File

@ -1502,9 +1502,9 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
} else {
_idField.set(entity, id);
}
} else {
id = (ID)_idField.get(entity);
}
id = (ID)_idField.get(entity);
}
} catch (final IllegalAccessException e) {
throw new CloudRuntimeException("Yikes! ", e);

View File

@ -229,4 +229,14 @@ public class QuotaTariffDaoImpl extends GenericDaoBase<QuotaTariffVO, Long> impl
return quotaTariffs.get(0);
}
@Override
public QuotaTariffVO findByIdIncludingRemoved(Long id) {
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaTariffVO>) status -> super.findByIdIncludingRemoved(id));
}
@Override
public QuotaTariffVO findByUuidIncludingRemoved(String uuid) {
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaTariffVO>) status -> super.findByUuidIncludingRemoved(uuid));
}
}

View File

@ -17,7 +17,7 @@
package org.apache.cloudstack.quota.vo;
import com.cloud.utils.DateUtil;
import org.apache.cloudstack.api.InternalIdentity;
import org.apache.cloudstack.quota.QuotaTariff;
import org.apache.cloudstack.quota.constant.QuotaTypes;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
@ -40,7 +40,7 @@ import java.util.UUID;
@Entity
@Table(name = "quota_tariff")
public class QuotaTariffVO implements InternalIdentity {
public class QuotaTariffVO implements QuotaTariff {
private static final long serialVersionUID = -7117933766387653203L;
@Id
@ -243,6 +243,7 @@ public class QuotaTariffVO implements InternalIdentity {
return description;
}
@Override
public String getUuid() {
return uuid;
}

View File

@ -20,6 +20,7 @@ import com.cloud.user.Account;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
@ -27,6 +28,7 @@ import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
import org.apache.cloudstack.api.response.QuotaTariffResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
import javax.inject.Inject;
@ -68,6 +70,7 @@ public class QuotaTariffCreateCmd extends BaseCmd {
@Override
public void execute() {
CallContext.current().setEventDetails(String.format("Tariff: %s, description: %s, value: %s", getName(), getDescription(), getValue()));
QuotaTariffVO result = responseBuilder.createQuotaTariff(this);
if (result == null) {
@ -132,4 +135,8 @@ public class QuotaTariffCreateCmd extends BaseCmd {
this.endDate = endDate;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.QuotaTariff;
}
}

View File

@ -21,12 +21,14 @@ import com.cloud.user.Account;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
import org.apache.cloudstack.api.response.QuotaTariffResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import javax.inject.Inject;
@ -47,6 +49,7 @@ public class QuotaTariffDeleteCmd extends BaseCmd {
@Override
public void execute() {
CallContext.current().setEventDetails(String.format("Tariff id: %s", getId()));
boolean result = responseBuilder.deleteQuotaTariff(getId());
SuccessResponse response = new SuccessResponse(getCommandName());
response.setSuccess(result);
@ -58,4 +61,8 @@ public class QuotaTariffDeleteCmd extends BaseCmd {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.QuotaTariff;
}
}

View File

@ -20,6 +20,7 @@ import com.cloud.user.Account;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
@ -27,6 +28,7 @@ import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
import org.apache.cloudstack.api.response.QuotaTariffResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
import javax.inject.Inject;
@ -109,6 +111,7 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
@Override
public void execute() {
CallContext.current().setEventDetails(String.format("Tariff: %s, description: %s, value: %s", getName(), getDescription(), getValue()));
final QuotaTariffVO result = _responseBuilder.updateQuotaTariffPlan(this);
if (result == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update quota tariff plan");
@ -123,4 +126,8 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
return Account.ACCOUNT_ID_SYSTEM;
}
@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.QuotaTariff;
}
}

View File

@ -44,6 +44,7 @@ import org.apache.cloudstack.api.command.QuotaStatementCmd;
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.quota.QuotaManager;
import org.apache.cloudstack.quota.QuotaManagerImpl;
import org.apache.cloudstack.quota.QuotaService;
@ -78,6 +79,8 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
@Component
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
@ -383,6 +386,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_QUOTA_TARIFF_UPDATE, eventDescription = "updating Quota Tariff")
public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) {
String name = cmd.getName();
Double value = cmd.getValue();
@ -406,6 +410,9 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(currentQuotaTariff, name, 0, currentQuotaTariffStartDate, cmd.getEntityOwnerId(), endDate, value, description,
activationRule);
_quotaTariffDao.updateQuotaTariff(currentQuotaTariff);
CallContext.current().setEventResourceId(newQuotaTariff.getId());
return newQuotaTariff;
}
@ -625,6 +632,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_QUOTA_TARIFF_CREATE, eventDescription = "creating Quota Tariff")
public QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd) {
String name = cmd.getName();
int usageType = cmd.getUsageType();
@ -647,9 +655,14 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
"Please, inform a date in the future or do not pass the parameter to use the current date and time.", startDate));
}
return persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule);
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule);
CallContext.current().setEventResourceId(newQuotaTariff.getId());
return newQuotaTariff;
}
@ActionEvent(eventType = EventTypes.EVENT_QUOTA_TARIFF_DELETE, eventDescription = "removing Quota Tariff")
public boolean deleteQuotaTariff(String quotaTariffUuid) {
QuotaTariffVO quotaTariff = _quotaTariffDao.findByUuid(quotaTariffUuid);
@ -658,6 +671,9 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
}
quotaTariff.setRemoved(_quotaService.computeAdjustedTime(new Date()));
CallContext.current().setEventResourceId(quotaTariff.getId());
return _quotaTariffDao.updateQuotaTariff(quotaTariff);
}
}

View File

@ -420,6 +420,9 @@ public class LibvirtDomainXMLParser {
}
private static String getTagValue(String tag, Element eElement) {
if (eElement == null) {
return null;
}
NodeList tagNodeList = eElement.getElementsByTagName(tag);
if (tagNodeList == null || tagNodeList.getLength() == 0) {
return null;
@ -427,14 +430,20 @@ public class LibvirtDomainXMLParser {
NodeList nlList = tagNodeList.item(0).getChildNodes();
if (nlList == null || nlList.getLength() == 0) {
return null;
}
Node nValue = nlList.item(0);
return nValue.getNodeValue();
}
private static String getAttrValue(String tag, String attr, Element eElement) {
if (eElement == null) {
return null;
}
NodeList tagNode = eElement.getElementsByTagName(tag);
if (tagNode.getLength() == 0) {
if (tag == null || tagNode.getLength() == 0) {
return null;
}
Element node = (Element)tagNode.item(0);

View File

@ -259,4 +259,126 @@ public class LibvirtDomainXMLParserTest extends TestCase {
assertEquals(WatchDogDef.WatchDogModel.I6300ESB, watchDogs.get(0).getModel());
assertEquals(WatchDogDef.WatchDogAction.RESET, watchDogs.get(0).getAction());
}
@Test
public void testDomainXMLParserWithoutModelName() {
String xml = "<domain type='kvm'>\n" +
" <name>testkiran</name>\n" +
" <uuid>aafaaabc-8657-4efc-9c52-3422d4e04088</uuid>\n" +
" <memory unit='KiB'>2097152</memory>\n" +
" <currentMemory unit='KiB'>2097152</currentMemory>\n" +
" <vcpu placement='static'>2</vcpu>\n" +
" <os>\n" +
" <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>\n" +
" <boot dev='hd'/>\n" +
" </os>\n" +
" <features>\n" +
" <acpi/>\n" +
" <apic/>\n" +
" </features>\n" +
" <cpu mode='host-model' check='partial'>\n" +
" <model fallback='allow'/>\n" +
" </cpu>\n" +
" <clock offset='utc'>\n" +
" <timer name='rtc' tickpolicy='catchup'/>\n" +
" <timer name='pit' tickpolicy='delay'/>\n" +
" <timer name='hpet' present='no'/>\n" +
" </clock>\n" +
" <on_poweroff>destroy</on_poweroff>\n" +
" <on_reboot>restart</on_reboot>\n" +
" <on_crash>destroy</on_crash>\n" +
" <pm>\n" +
" <suspend-to-mem enabled='no'/>\n" +
" <suspend-to-disk enabled='no'/>\n" +
" </pm>\n" +
" <devices>\n" +
" <emulator>/usr/libexec/qemu-kvm</emulator>\n" +
" <disk type='file' device='disk'>\n" +
" <driver name='qemu' type='qcow2'/>\n" +
" <source file='/var/lib/libvirt/images/ubuntu-22.04.qcow2'/>\n" +
" <target dev='vda' bus='virtio'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>\n" +
" </disk>\n" +
" <disk type='file' device='disk'>\n" +
" <driver name='qemu' type='qcow2'/>\n" +
" <source file='/var/lib/libvirt/images/testkiran.qcow2'/>\n" +
" <target dev='vdb' bus='virtio'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>\n" +
" </disk>\n" +
" <controller type='usb' index='0' model='ich9-ehci1'>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x7'/>\n" +
" </controller>\n" +
" <controller type='usb' index='0' model='ich9-uhci1'>\n" +
" <master startport='0'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' multifunction='on'/>\n" +
" </controller>\n" +
" <controller type='usb' index='0' model='ich9-uhci2'>\n" +
" <master startport='2'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x1'/>\n" +
" </controller>\n" +
" <controller type='usb' index='0' model='ich9-uhci3'>\n" +
" <master startport='4'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x2'/>\n" +
" </controller>\n" +
" <controller type='pci' index='0' model='pci-root'/>\n" +
" <controller type='virtio-serial' index='0'>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>\n" +
" </controller>\n" +
" <interface type='network'>\n" +
" <mac address='52:54:00:09:73:b8'/>\n" +
" <source network='default'/>\n" +
" <model type='virtio'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n" +
" </interface>\n" +
" <serial type='pty'>\n" +
" <target type='isa-serial' port='0'>\n" +
" <model name='isa-serial'/>\n" +
" </target>\n" +
" </serial>\n" +
" <console type='pty'>\n" +
" <target type='serial' port='0'/>\n" +
" </console>\n" +
" <channel type='spicevmc'>\n" +
" <target type='virtio' name='com.redhat.spice.0'/>\n" +
" <address type='virtio-serial' controller='0' bus='0' port='1'/>\n" +
" </channel>\n" +
" <input type='tablet' bus='usb'>\n" +
" <address type='usb' bus='0' port='1'/>\n" +
" </input>\n" +
" <input type='mouse' bus='ps2'/>\n" +
" <input type='keyboard' bus='ps2'/>\n" +
" <graphics type='vnc' port='-1' autoport='yes'>\n" +
" <listen type='address'/>\n" +
" </graphics>\n" +
" <graphics type='spice' autoport='yes'>\n" +
" <listen type='address'/>\n" +
" <image compression='off'/>\n" +
" </graphics>\n" +
" <sound model='ich6'>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>\n" +
" </sound>\n" +
" <video>\n" +
" <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>\n" +
" </video>\n" +
" <redirdev bus='usb' type='spicevmc'>\n" +
" <address type='usb' bus='0' port='2'/>\n" +
" </redirdev>\n" +
" <redirdev bus='usb' type='spicevmc'>\n" +
" <address type='usb' bus='0' port='3'/>\n" +
" </redirdev>\n" +
" <memballoon model='virtio'>\n" +
" <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>\n" +
" </memballoon>\n" +
" </devices>\n" +
"</domain>";
LibvirtDomainXMLParser libvirtDomainXMLParser = new LibvirtDomainXMLParser();
try {
libvirtDomainXMLParser.parseDomainXML(xml);
} catch (Exception e) {
System.out.println("Got exception " + e.getMessage());
throw e;
}
}
}

View File

@ -59,6 +59,7 @@ import com.cloud.api.storage.LinstorRevertBackupSnapshotCommand;
import com.cloud.configuration.Config;
import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.resource.ResourceState;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ResizeVolumePayload;
import com.cloud.storage.SnapshotVO;
@ -215,6 +216,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
}
throw new CloudRuntimeException("Linstor: Unable to delete resource definition: " + rscDefName);
}
logger.info(String.format("Linstor: Deleted resource %s", rscDefName));
} catch (ApiException apiEx)
{
logger.error("Linstor: ApiEx - " + apiEx.getMessage());
@ -865,7 +867,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
Host host = null;
for (String nodeName : linstorNodeNames) {
host = _hostDao.findByName(nodeName);
if (host != null) {
if (host != null && host.getResourceState() == ResourceState.Enabled) {
logger.info(String.format("Linstor: Make resource %s available on node %s ...", rscName, nodeName));
ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, nodeName, new ResourceMakeAvailable());
if (!answers.hasError()) {
@ -892,21 +894,16 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
}
private Optional<RemoteHostEndPoint> getDiskfullEP(DevelopersApi api, String rscName) throws ApiException {
com.linbit.linstor.api.model.StoragePool linSP =
LinstorUtil.getDiskfulStoragePool(api, rscName);
if (linSP != null)
{
Host host = _hostDao.findByName(linSP.getNodeName());
if (host == null)
{
logger.error("Linstor: Host '" + linSP.getNodeName() + "' not found.");
return Optional.empty();
}
else
{
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
List<com.linbit.linstor.api.model.StoragePool> linSPs = LinstorUtil.getDiskfulStoragePools(api, rscName);
if (linSPs != null) {
for (com.linbit.linstor.api.model.StoragePool sp : linSPs) {
Host host = _hostDao.findByName(sp.getNodeName());
if (host != null && host.getResourceState() == ResourceState.Enabled) {
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
}
}
}
logger.error("Linstor: No diskfull host found.");
return Optional.empty();
}
@ -958,9 +955,11 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
}
else {
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
deleteResourceDefinition(pool, rscName);
}
} catch (ApiException exc) {
logger.error("copy template failed: ", exc);
deleteResourceDefinition(pool, rscName);
throw new CloudRuntimeException(exc.getBestMessage());
}
return answer;

View File

@ -78,16 +78,16 @@ public class LinstorUtil {
return nodes.stream().map(Node::getName).collect(Collectors.toList());
}
public static com.linbit.linstor.api.model.StoragePool
getDiskfulStoragePool(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException
public static List<com.linbit.linstor.api.model.StoragePool>
getDiskfulStoragePools(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException
{
List<ResourceWithVolumes> resources = api.viewResources(
Collections.emptyList(),
Collections.singletonList(rscName),
Collections.emptyList(),
Collections.emptyList(),
null,
null);
Collections.emptyList(),
Collections.singletonList(rscName),
Collections.emptyList(),
Collections.emptyList(),
null,
null);
String nodeName = null;
String storagePoolName = null;
@ -108,13 +108,23 @@ public class LinstorUtil {
}
List<com.linbit.linstor.api.model.StoragePool> sps = api.viewStoragePools(
Collections.singletonList(nodeName),
Collections.singletonList(storagePoolName),
Collections.emptyList(),
null,
null
Collections.singletonList(nodeName),
Collections.singletonList(storagePoolName),
Collections.emptyList(),
null,
null
);
return !sps.isEmpty() ? sps.get(0) : null;
return sps != null ? sps : Collections.emptyList();
}
public static com.linbit.linstor.api.model.StoragePool
getDiskfulStoragePool(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException
{
List<com.linbit.linstor.api.model.StoragePool> sps = getDiskfulStoragePools(api, rscName);
if (sps != null) {
return !sps.isEmpty() ? sps.get(0) : null;
}
return null;
}
public static String getSnapshotPath(com.linbit.linstor.api.model.StoragePool sp, String rscName, String snapshotName) {

View File

@ -553,7 +553,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
List<StoragePoolVO> pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId());
pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId()));
for (StoragePool pool : pools) {
if (StringUtils.contains(pool.getPath(), dsPath)) {
String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName;
if (StringUtils.contains(pool.getPath(), searchPoolParam)) {
storagePool = pool;
break;
}

View File

@ -339,7 +339,8 @@ export default {
{ value: 'Template' },
{ value: 'User' },
{ value: 'VirtualMachine' },
{ value: 'Volume' }
{ value: 'Volume' },
{ value: 'QuotaTariff' }
]
this.fields[resourceTypeIndex].loading = false
}

View File

@ -58,11 +58,11 @@ export default {
created () {
if (this.resourceType) {
var routePrefix = this.$getRouteFromResourceType(this.resourceType)
if (routePrefix && this.resourceId) {
if (routePrefix && this.resourceId && this.resourceType !== 'QuotaTariff') {
this.resourceRoute = '/' + routePrefix + '/' + this.resourceId
}
this.resourceIcon = this.$getIconFromResourceType(this.resourceType)
this.resourceIconTooltip = this.$t('label.' + this.resourceType.toString().toLowerCase())
this.resourceIconTooltip = this.$t('label.' + this.resourceType.toString().match(/[A-Z][a-z]*/g).join('.').toLowerCase())
}
}
}

View File

@ -31,9 +31,9 @@ export default {
permission: ['listVirtualMachinesMetrics'],
resourceType: 'UserVm',
params: () => {
var params = { details: 'servoff,tmpl,nics,backoff' }
var params = { details: 'servoff,tmpl,iso,nics,backoff' }
if (store.getters.metrics) {
params = { details: 'servoff,tmpl,nics,backoff,stats' }
params = { details: 'servoff,tmpl,iso,nics,backoff,stats' }
}
params.isvnf = false
return params

View File

@ -417,6 +417,7 @@ export const resourceTypePlugin = {
case 'AffinityGroup':
case 'VpnCustomerGateway':
case 'AutoScaleVmGroup':
case 'QuotaTariff':
return resourceType.toLowerCase()
}
return ''