diff --git a/tests/vosi/VOSIAvailability-v1.0.xsd b/tests/vosi/VOSIAvailability-v1.0.xsd
new file mode 100644
index 0000000..7c72bc3
--- /dev/null
+++ b/tests/vosi/VOSIAvailability-v1.0.xsd
@@ -0,0 +1,73 @@
+
+
+
+
+
+ A schema for formatting availability metadata as returned by an
+ availability resource defined in the IVOA Support Interfaces
+ specification (VOSI).
+ See http://www.ivoa.net/Documents/latest/VOSI.html.
+
+
+
+
+
+
+
+
+
+
+
+
+ Indicates whether the service is currently available.
+
+
+
+
+
+
+
+ The instant at which the service last became available.
+
+
+
+
+
+
+
+ The instant at which the service is next scheduled to become
+ unavailable.
+
+
+
+
+
+
+
+ The instant at which the service is scheduled to become available
+ again after a period of unavailability.
+
+
+
+
+
+
+
+ A textual note concerning availability.
+
+
+
+
+
+
+
+
diff --git a/tests/vosi/__init__.py b/tests/vosi/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/vosi/availability_test.py b/tests/vosi/availability_test.py
new file mode 100644
index 0000000..12bae51
--- /dev/null
+++ b/tests/vosi/availability_test.py
@@ -0,0 +1,59 @@
+"""Tests for VOSI Availability models."""
+
+from datetime import timezone as tz
+from unittest import TestCase
+from xml.etree.ElementTree import canonicalize
+
+from lxml import etree
+
+with open("tests/vosi/VOSIAvailability-v1.0.xsd") as f:
+ availability_schema = etree.parse(f)
+
+from vo_models.xml.vosi.availability import Availability
+from vo_models.xml.generics import VODateTime
+
+VOSI_AVAILABILITY_HEADER = """xmlns="http://www.ivoa.net/xml/VOSIAvailability/v1.0"
+xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+"""
+
+class TestVOSIAvailabilityType(TestCase):
+ """Tests the VOSI Availability complex type."""
+
+ test_avaiability_xml = f"""
+ true
+ 2021-01-01T00:00:00.000Z
+ 2021-01-01T00:00:00.000Z
+ 2021-01-01T00:00:00.000Z
+ Test note
+ """
+
+ def test_read_from_xml(self):
+ """Test reading Availability from XML."""
+ availability = Availability.from_xml(self.test_avaiability_xml)
+ self.assertTrue(availability.available)
+ self.assertEqual(availability.up_since, VODateTime(2021, 1, 1, tzinfo=tz.utc))
+ self.assertEqual(availability.down_at, VODateTime(2021, 1, 1, tzinfo=tz.utc))
+ self.assertEqual(availability.back_at, VODateTime(2021, 1, 1, tzinfo=tz.utc))
+ self.assertEqual(availability.note, ["Test note"])
+
+ def test_write_to_xml(self):
+ """Test writing Availability to XML."""
+ availability = Availability(
+ available=True,
+ up_since="2021-01-01T00:00:00.000Z",
+ down_at="2021-01-01T00:00:00.000Z",
+ back_at="2021-01-01T00:00:00.000Z",
+ note=["Test note"],
+ )
+
+ with open("debug.xml", "w") as f:
+ f.write(canonicalize(availability.to_xml()))
+ f.write("\n")
+ f.write(canonicalize(self.test_avaiability_xml))
+
+ availability_xml = availability.to_xml()
+ self.assertEqual(
+ canonicalize(availability_xml, strip_text=True),
+ canonicalize(self.test_avaiability_xml, strip_text=True),
+ )
\ No newline at end of file
diff --git a/vo_models/xml/vosi/__init__.py b/vo_models/xml/vosi/__init__.py
new file mode 100644
index 0000000..a6b6c8b
--- /dev/null
+++ b/vo_models/xml/vosi/__init__.py
@@ -0,0 +1 @@
+"""Module containing VOSI (VO Service Interface) classes."""
diff --git a/vo_models/xml/vosi/availability.py b/vo_models/xml/vosi/availability.py
new file mode 100644
index 0000000..29b0fc5
--- /dev/null
+++ b/vo_models/xml/vosi/availability.py
@@ -0,0 +1,32 @@
+"""VOSIAvailability pydantic-xml models."""
+
+from typing import Optional
+
+from pydantic_xml import BaseXmlModel, element
+
+from vo_models.xml.generics import VODateTime
+
+NSMAP = {
+ "": "http://www.ivoa.net/xml/VOSIAvailability/v1.0",
+ "xsd": "http://www.w3.org/2001/XMLSchema",
+ "xsi": "http://www.w3.org/2001/XMLSchema-instance",
+}
+
+
+class Availability(BaseXmlModel, tag="availability", nsmap=NSMAP):
+ """VOSI Availability complex type.
+
+ Elements:
+ available (bool): Whether the service is currently available.
+ upSince (datetime): The instant at which the service last became available.
+ downAt (datetime): The instant at which the service is next scheduled to become unavailable.
+ backAt (datetime): The instant at which the service is scheduled to become available again after a period
+ of unavailability.
+ note (str): A textual note concerning availability.
+ """
+
+ available: bool = element(tag="available")
+ up_since: Optional[VODateTime] = element(tag="upSince")
+ down_at: Optional[VODateTime] = element(tag="downAt")
+ back_at: Optional[VODateTime] = element(tag="backAt")
+ note: Optional[list[str]] = element(tag="note")