From 91c38f36058d159216c945321b80727ae28e5d6d Mon Sep 17 00:00:00 2001 From: ysssasaki <64194789+ysssasaki@users.noreply.github.com> Date: Thu, 17 Mar 2022 13:42:23 +0900 Subject: [PATCH 01/19] Support security group (#101) * Revert "Revert ":sparkles: IF-6816 add security groups api (#89)" (#96)" This reverts commit a77f2df99e25061e6e95eafa813569c8ed7ec0a0. * Revert "Revert ":sparkles: IF-7067 add security group rules api (#90)" (#95)" This reverts commit 1edbfbc2f4139684d887ebc947c61cb35f645ae0. * Revert "Revert ":bug: IF-7068 fix existing api (#91)" (#94)" This reverts commit c5b99e18c5adb34f46194ef4ffec5dff1efb90ae. * :sparkles: IF-7192 security groups api query support (#93) - List Security Group API - List Security Group Rule API Co-authored-by: a-oi-xon Co-authored-by: a-oi-xon <91597807+a-oi-xon@users.noreply.github.com> --- ecl/network/v2/_proxy.py | 189 +++++++++++++++++- ecl/network/v2/port.py | 3 + ecl/network/v2/quota.py | 2 + ecl/network/v2/security_group.py | 39 ++++ ecl/network/v2/security_group_rule.py | 52 +++++ ecl/tests/unit/network/v2/test_port.py | 12 +- ecl/tests/unit/network/v2/test_quota.py | 25 ++- .../unit/network/v2/test_security_group.py | 59 ++++++ .../network/v2/test_security_group_rule.py | 59 ++++++ 9 files changed, 422 insertions(+), 18 deletions(-) create mode 100644 ecl/network/v2/security_group.py create mode 100644 ecl/network/v2/security_group_rule.py create mode 100644 ecl/tests/unit/network/v2/test_security_group.py create mode 100644 ecl/tests/unit/network/v2/test_security_group_rule.py diff --git a/ecl/network/v2/_proxy.py b/ecl/network/v2/_proxy.py index 7644fb4..46e86a3 100755 --- a/ecl/network/v2/_proxy.py +++ b/ecl/network/v2/_proxy.py @@ -13,6 +13,8 @@ from ecl.network.v2 import physical_port as _physical_port from ecl.network.v2 import quota as _quota from ecl.network.v2 import reserved_address as _reserved_address +from ecl.network.v2 import security_group as _security_group +from ecl.network.v2 import security_group_rule as _security_group_rule from ecl.network.v2 import firewall as _firewall from ecl.network.v2 import firewall_interface as _firewall_if from ecl.network.v2 import firewall_plan as _firewall_plan @@ -188,7 +190,7 @@ def get_extension(self, extension): def create_port(self, admin_state_up=None, allowed_address_pairs=None, mac_address=None, description=None, device_id=None, device_owner=None, fixed_ips=None, name=None, - network_id=None, segmentation_id=None, + network_id=None, security_groups=None, segmentation_id=None, segmentation_type=None, tags=None): """Create a new port from attributes @@ -203,6 +205,7 @@ def create_port(self, admin_state_up=None, allowed_address_pairs=None, e.g. [{"ip_address": , "subnet_id": }, ] :param string name: The name of port to create :param string network_id: The network id of port to create + :param array security_groups: The security groups ids of port to create :param int segmentation_id: The segmentation id of port to create :param string segmentation_type: The segmentation type of port to create :param dict tags: tags of port @@ -229,6 +232,8 @@ def create_port(self, admin_state_up=None, allowed_address_pairs=None, body["name"] = name if network_id: body["network_id"] = network_id + if security_groups: + body["security_groups"] = security_groups if segmentation_id: body["segmentation_id"] = segmentation_id if segmentation_type: @@ -305,6 +310,7 @@ def update_port(self, port, **params): * array fixed_ips: The fixed ips of port to update e.g. [{"ip_address": , "subnet_id": }, ] * string name: The name of port to update + * array security_groups: The security groups ids of port to update * int segmentation_id: The segmentation id of port to update * string segmentation_type: The segmentation type of port to update * dict tags: tags of port @@ -498,6 +504,187 @@ def get_reserved_address(self, reserved_address): """ return self._get(_reserved_address.ReservedAddress, reserved_address) + def security_groups(self, **query): + """ List all visible security-groups. + + :param query: Query parameters to select results + :return: A list of security-group objects + :rtype: :class:`~ecl.network.v2.security_group.SecurityGroup` + """ + return list(self._list(_security_group.SecurityGroup, + paginated=False, **query)) + + def create_security_group(self, description=None, name=None, tags=None, + tenant_id=None): + """Create security-group. + + :param string description: Security group description. + :param string name: Security group name. + :param dict tags: Security Group tags. + :param string tenant_id: The owner name of security group. + :returns: The results of security-group creation + :rtype: :class:`~ecl.network.v2.security_group.SecurityGroup` + """ + body = dict() + if description: + body["description"] = description + if name: + body["name"] = name + if tags: + body["tags"] = tags + if tenant_id: + body["tenant_id"] = tenant_id + + return self._create(_security_group.SecurityGroup, **body) + + def get_security_group(self, security_group): + """Show details for security-group. + + :param security_group: The value can be the ID of a security-group or + a :class:`~ecl.network.v2.security_group.SecurityGroup` instance. + :returns: One :class:`~ecl.network.v2.security_group.SecurityGroup` + :raises: :class:`~ecl.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_security_group.SecurityGroup, security_group) + + def update_security_group(self, security_group, **params): + """Update security-group. + + :param security_group: Either the id of a security-group or + a :class:`~ecl.network.v2.security_group.SecurityGroup` instance. + :param kwargs params: Parameters for security-group update. + + * string description: Security group description. + * string name: Security group name. + * dict tags: Security Group tags. + + :returns: The updated security-group + :rtype: :class:`~ecl.network.v2.security_group.SecurityGroup` + """ + if not isinstance(security_group, _security_group.SecurityGroup): + # security_group is the ID + security_group = self._get_resource(_security_group.SecurityGroup, + security_group) + security_group._body.clean() + + return self._update(_security_group.SecurityGroup, + security_group, **params) + + def delete_security_group(self, security_group, ignore_missing=False): + """Delete security-group. + + :param security_group: The value can be either the ID of + a security-group or + a :class:`~ecl.network.v2.security_group.SecurityGroup` instance. + :param bool ignore_missing: When set to ``False`` :class: + `~ecl.exceptions.ResourceNotFound` will + be raised when the security-group does + not exist. When set to ``True``, + no exception will be set when attempting + to delete a nonexistent security-group. + :returns: ``None`` + """ + self._delete(_security_group.SecurityGroup, security_group, + ignore_missing=ignore_missing) + + def security_group_rules(self, **query): + """ List all visible security-group-rules. + + :param query: Query parameters to select results + :return: A list of security-group-rule objects + :rtype: :class:`~ecl.network.v2.security_group_rule.SecurityGroupRule` + """ + return list(self._list(_security_group_rule.SecurityGroupRule, + paginated=False, **query)) + + def create_security_group_rule(self, security_group_id, direction, + description=None, ethertype=None, + port_range_max=None, port_range_min=None, + protocol=None, remote_group_id=None, + remote_ip_prefix=None, tenant_id=None): + """Create security-group-rule. + + :param string security_group_id: Security group id. + :param string direction: Direction in which the security group rule + is applied. + :param string description: Security group rule description. + :param string ethertype: Addresses represented in CIDR must match + the ingress or egress rules. + :param int port_range_max: The maximum port number in the range that + is matched by the security group rule. + :param int port_range_min: The minimum port number in the range that + is matched by the security group rule. + :param string protocol: Protocol name or number in string format. + e.g. "ICMP" or "1" + :param string remote_group_id: The remote group UUID to associate + with this security group rule. Only + either one of remote_group_id and + remote_ip_prefix have to be specified. + :param string remote_ip_prefix: The IP address prefix to associate + with this security group rule. Only + either one of remote_group_id and + remote_ip_prefix have to be specified. + :param string tenant_id: The owner name of security group rule. + :returns: The results of security-group-rule creation + :rtype: :class:`~ecl.network.v2.security_group_rule.SecurityGroupRule` + """ + body = { + "security_group_id": security_group_id, + "direction": direction + } + if description: + body["description"] = description + if ethertype: + body["ethertype"] = ethertype + if port_range_max is not None: + body["port_range_max"] = port_range_max + if port_range_min is not None: + body["port_range_min"] = port_range_min + if protocol: + body["protocol"] = protocol + if remote_group_id: + body["remote_group_id"] = remote_group_id + if remote_ip_prefix: + body["remote_ip_prefix"] = remote_ip_prefix + if tenant_id: + body["tenant_id"] = tenant_id + + return self._create(_security_group_rule.SecurityGroupRule, **body) + + def get_security_group_rule(self, security_group_rule): + """Show details for security-group-rule. + + :param security_group_rule: The value can be the ID of + a security-group-rule or + a :class:`~ecl.network.v2.security_group_rule.SecurityGroupRule` + instance. + :returns: :class:`~ecl.network.v2.security_group_rule.SecurityGroupRule` + :raises: :class:`~ecl.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_security_group_rule.SecurityGroupRule, + security_group_rule) + + def delete_security_group_rule(self, security_group_rule, + ignore_missing=False): + """Delete security-group-rule. + + :param security_group_rule: The value can be either the ID of + a security-group-rule or + a :class:`~ecl.network.v2.security_group_rule.SecurityGroupRule` + instance. + :param bool ignore_missing: When set to ``False`` :class: + `~ecl.exceptions.ResourceNotFound` will + be raised when the security-group-rule does + not exist. When set to ``True``, + no exception will be set when attempting + to delete a nonexistent security-group-rule. + :returns: ``None`` + """ + self._delete(_security_group_rule.SecurityGroupRule, + security_group_rule, ignore_missing=ignore_missing) + def firewalls(self, **query): """ List all visible firewalls. diff --git a/ecl/network/v2/port.py b/ecl/network/v2/port.py index 9963a65..66b49f4 100755 --- a/ecl/network/v2/port.py +++ b/ecl/network/v2/port.py @@ -73,6 +73,9 @@ class Port(base.NetworkBaseResource): #: users can specify a project ID other than their own. project_id = resource2.Body('tenant_id') + #: The IDs of security groups applied to the port. + security_groups = resource2.Body('security_groups') + #: The segmentation ID of ports. segmentation_id = resource2.Body('segmentation_id', type=int) diff --git a/ecl/network/v2/quota.py b/ecl/network/v2/quota.py index c4432c0..e3d30cd 100755 --- a/ecl/network/v2/quota.py +++ b/ecl/network/v2/quota.py @@ -47,6 +47,8 @@ class Quota(resource2.Resource): vpn_gateway = resource2.Body('vpn_gateway', type=int) #: The maximum amount of public ip you can create. *Type: int* public_ip = resource2.Body('public_ip', type=int) + #: The maximum amount of security group you can create. *Type: int* + security_group = resource2.Body('security_group', type=int) class QuotaDefault(Quota): diff --git a/ecl/network/v2/security_group.py b/ecl/network/v2/security_group.py new file mode 100644 index 0000000..f371429 --- /dev/null +++ b/ecl/network/v2/security_group.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +from ecl.network import network_service +from ecl import resource2 + + +class SecurityGroup(resource2.Resource): + """SecurityGroup Resource""" + resource_key = 'security_group' + resources_key = 'security_groups' + service = network_service.NetworkService("v2.0") + base_path = '/' + service.version + '/security-groups' + + # query parameter names + _query_mapping = resource2.QueryParameters( + 'description', 'id', 'name', 'status', 'tenant_id') + + # capabilities + allow_list = True + allow_create = True + allow_get = True + allow_update = True + allow_delete = True + + # Properties + # Security group description. + description = resource2.Body('description') + # Security group unique id. + id = resource2.Body('id') + # Security group name. + name = resource2.Body('name') + # Security group status. + status = resource2.Body('status') + # Security Group tags. + tags = resource2.Body('tags') + # The owner name of security group. + tenant_id = resource2.Body('tenant_id') + # Security group rules + security_group_rules = resource2.Body('security_group_rules', type=list) diff --git a/ecl/network/v2/security_group_rule.py b/ecl/network/v2/security_group_rule.py new file mode 100644 index 0000000..541e9fb --- /dev/null +++ b/ecl/network/v2/security_group_rule.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +from ecl.network import network_service +from ecl import resource2 + + +class SecurityGroupRule(resource2.Resource): + """SecurityGroupRule Resource""" + resource_key = 'security_group_rule' + resources_key = 'security_group_rules' + service = network_service.NetworkService("v2.0") + base_path = '/' + service.version + '/security-group-rules' + + # query parameter names + _query_mapping = resource2.QueryParameters( + 'description', 'direction', 'ethertype', 'id', 'port_range_max', + 'port_range_min', 'protocol', 'remote_group_id', 'remote_ip_prefix', + 'security_group_id', 'tenant_id') + + # capabilities + allow_list = True + allow_create = True + allow_get = True + allow_delete = True + + # Properties + # Security group rule description. + description = resource2.Body('description') + # Direction in which the security group rule is applied. + direction = resource2.Body('direction') + # Addresses represented in CIDR must match the ingress or egress rules. + ethertype = resource2.Body('ethertype') + # Security group rule unique id. + id = resource2.Body('id') + # The maximum port number in the range that is matched + # by the security group rule. + port_range_max = resource2.Body('port_range_max', type=int) + # The minimum port number in the range that is matched + # by the security group rule. + port_range_min = resource2.Body('port_range_min', type=int) + # Protocol name or number in string format. e.g. "ICMP" or "1" + protocol = resource2.Body('protocol') + # The remote group UUID to associate with this security group rule. Only + # either one of remote_group_id and remote_ip_prefix have to be specified. + remote_group_id = resource2.Body('remote_group_id') + # The IP address prefix to associate with this security group rule. Only + # either one of remote_group_id and remote_ip_prefix have to be specified. + remote_ip_prefix = resource2.Body('remote_ip_prefix') + # Security group id. + security_group_id = resource2.Body('security_group_id') + # The owner name of security group rule. + tenant_id = resource2.Body('tenant_id') diff --git a/ecl/tests/unit/network/v2/test_port.py b/ecl/tests/unit/network/v2/test_port.py index e08bbca..d130828 100755 --- a/ecl/tests/unit/network/v2/test_port.py +++ b/ecl/tests/unit/network/v2/test_port.py @@ -12,7 +12,7 @@ import testtools -from ecl.network.v2 import port +from ecl.network.v2.port import Port IDENTIFIER = 'IDENTIFIER' EXAMPLE = { @@ -30,6 +30,9 @@ "mac_address": "test-mac", "name": "Example port 1", "network_id": IDENTIFIER, + "security_groups": [ + IDENTIFIER + ], "segmentation_id": 0, "segmentation_type": "flat", "tags": { @@ -44,10 +47,10 @@ class TestPort(testtools.TestCase): def test_basic(self): - sot = port.Port() + sot = Port() self.assertEqual('port', sot.resource_key) self.assertEqual('ports', sot.resources_key) - self.assertEqual('/ports', sot.base_path) + self.assertEqual('/v2.0/ports', sot.base_path) self.assertEqual('network', sot.service.service_type) self.assertTrue(sot.allow_create) self.assertTrue(sot.allow_get) @@ -56,7 +59,7 @@ def test_basic(self): self.assertTrue(sot.allow_list) def test_make_it(self): - sot = port.Port(**EXAMPLE) + sot = Port(**EXAMPLE) self.assertTrue(sot.admin_state_up) self.assertEqual('UP', sot.admin_state) self.assertEqual(EXAMPLE['allowed_address_pairs'], @@ -68,6 +71,7 @@ def test_make_it(self): self.assertEqual(EXAMPLE['mac_address'], sot.mac_address) self.assertEqual(EXAMPLE['name'], sot.name) self.assertEqual(EXAMPLE['network_id'], sot.network_id) + self.assertEqual(EXAMPLE['security_groups'], sot.security_groups) self.assertEqual(EXAMPLE['segmentation_id'], sot.segmentation_id) self.assertEqual(EXAMPLE['segmentation_type'], sot.segmentation_type) self.assertEqual(EXAMPLE['tags'], sot.tags) diff --git a/ecl/tests/unit/network/v2/test_quota.py b/ecl/tests/unit/network/v2/test_quota.py index 113bff0..25c6386 100755 --- a/ecl/tests/unit/network/v2/test_quota.py +++ b/ecl/tests/unit/network/v2/test_quota.py @@ -12,7 +12,7 @@ import testtools -from ecl.network.v2 import quota +from ecl.network.v2.quota import Quota, QuotaDefault IDENTIFIER = 'IDENTIFIER' EXAMPLE = { @@ -34,14 +34,13 @@ } - class TestQuota(testtools.TestCase): def test_basic(self): - sot = quota.Quota() + sot = Quota() self.assertEqual('quota', sot.resource_key) self.assertEqual('quotas', sot.resources_key) - self.assertEqual('/quotas', sot.base_path) + self.assertEqual('/v2.0/quotas', sot.base_path) self.assertEqual('network', sot.service.service_type) self.assertFalse(sot.allow_create) self.assertTrue(sot.allow_get) @@ -50,7 +49,7 @@ def test_basic(self): self.assertTrue(sot.allow_list) def test_make_it(self): - sot = quota.Quota(**EXAMPLE) + sot = Quota(**EXAMPLE) self.assertEqual(EXAMPLE['colocation_logical_link'], sot.colocation_logical_link) self.assertEqual(EXAMPLE['common_function_gateway'], sot.common_function_gateway) self.assertEqual(EXAMPLE['firewall'], sot.firewall) @@ -58,9 +57,9 @@ def test_make_it(self): self.assertEqual(EXAMPLE['interdc_gateway'], sot.interdc_gateway) self.assertEqual(EXAMPLE['interdc_gateway'], sot.internet_gateway) self.assertEqual(EXAMPLE['load_balancer'], sot.load_balancer) - self.assertEqual(EXAMPLE['network'], sot.networks) - self.assertEqual(EXAMPLE['port'], sot.ports) - self.assertEqual(EXAMPLE['subnet'], sot.subnets) + self.assertEqual(EXAMPLE['network'], sot.network) + self.assertEqual(EXAMPLE['port'], sot.port) + self.assertEqual(EXAMPLE['subnet'], sot.subnet) self.assertEqual(EXAMPLE['tenant_id'], sot.project_id) self.assertEqual(EXAMPLE['vpn_gateway'], sot.vpn_gateway) self.assertEqual(EXAMPLE['security_group'], sot.security_group) @@ -70,7 +69,7 @@ def test_make_it(self): class TestQuotaDefault(testtools.TestCase): def test_basic(self): - default = quota.QuotaDefault() + default = QuotaDefault() self.assertEqual('quota', default.resource_key) self.assertEqual('quotas', default.resources_key) self.assertEqual('/quotas/%(project)s/default', default.base_path) @@ -82,7 +81,7 @@ def test_basic(self): self.assertFalse(default.allow_list) def test_make_it(self): - default = quota.QuotaDefault(**EXAMPLE) + default = QuotaDefault(**EXAMPLE) self.assertEqual(EXAMPLE['colocation_logical_link'], default.colocation_logical_link) self.assertEqual(EXAMPLE['common_function_gateway'], default.common_function_gateway) self.assertEqual(EXAMPLE['firewall'], default.firewall) @@ -90,9 +89,9 @@ def test_make_it(self): self.assertEqual(EXAMPLE['interdc_gateway'], default.interdc_gateway) self.assertEqual(EXAMPLE['interdc_gateway'], default.internet_gateway) self.assertEqual(EXAMPLE['load_balancer'], default.load_balancer) - self.assertEqual(EXAMPLE['network'], default.networks) - self.assertEqual(EXAMPLE['port'], default.ports) - self.assertEqual(EXAMPLE['subnet'], default.subnets) + self.assertEqual(EXAMPLE['network'], default.network) + self.assertEqual(EXAMPLE['port'], default.port) + self.assertEqual(EXAMPLE['subnet'], default.subnet) self.assertEqual(EXAMPLE['tenant_id'], default.project_id) self.assertEqual(EXAMPLE['vpn_gateway'], default.vpn_gateway) self.assertEqual(EXAMPLE['security_group'], default.security_group) diff --git a/ecl/tests/unit/network/v2/test_security_group.py b/ecl/tests/unit/network/v2/test_security_group.py new file mode 100644 index 0000000..cd77239 --- /dev/null +++ b/ecl/tests/unit/network/v2/test_security_group.py @@ -0,0 +1,59 @@ +# Licensed 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. + +import testtools + +from ecl.network.v2.security_group import SecurityGroup + +IDENTIFIER = 'IDENTIFIER' +EXAMPLE = { + "description": '1', + "id": IDENTIFIER, + "name": '2', + "status": '3', + "tags": { + 'tag1': '4', + 'tag2': '5' + }, + "tenant_id": IDENTIFIER, + "security_group_rules": [ + { + 'rule1': '6', + 'rule2': '7' + } + ] +} + + +class TestSecurityGroup(testtools.TestCase): + + def test_basic(self): + sot = SecurityGroup() + self.assertEqual('security_group', sot.resource_key) + self.assertEqual('security_groups', sot.resources_key) + self.assertEqual('/v2.0/security-groups', sot.base_path) + self.assertEqual('network', sot.service.service_type) + self.assertTrue(sot.allow_list) + self.assertTrue(sot.allow_create) + self.assertTrue(sot.allow_get) + self.assertTrue(sot.allow_update) + self.assertTrue(sot.allow_delete) + + def test_make_it(self): + sot = SecurityGroup(**EXAMPLE) + self.assertEqual(EXAMPLE['description'], sot.description) + self.assertEqual(EXAMPLE['id'], sot.id) + self.assertEqual(EXAMPLE['name'], sot.name) + self.assertEqual(EXAMPLE['status'], sot.status) + self.assertEqual(EXAMPLE['tags'], sot.tags) + self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) + self.assertEqual(EXAMPLE['security_group_rules'], sot.security_group_rules) diff --git a/ecl/tests/unit/network/v2/test_security_group_rule.py b/ecl/tests/unit/network/v2/test_security_group_rule.py new file mode 100644 index 0000000..9760ed6 --- /dev/null +++ b/ecl/tests/unit/network/v2/test_security_group_rule.py @@ -0,0 +1,59 @@ +# Licensed 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. + +import testtools + +from ecl.network.v2.security_group_rule import SecurityGroupRule + +IDENTIFIER = 'IDENTIFIER' +EXAMPLE = { + 'description': '1', + 'direction': '2', + 'ethertype': '3', + 'id': IDENTIFIER, + 'port_range_min': 4, + 'port_range_max': 5, + 'protocol': '6', + 'remote_group_id': IDENTIFIER, + 'remote_ip_prefix': '7', + 'security_group_id': IDENTIFIER, + 'tenant_id': IDENTIFIER, +} + + +class TestSecurityGroupRule(testtools.TestCase): + + def test_basic(self): + sot = SecurityGroupRule() + self.assertEqual('security_group_rule', sot.resource_key) + self.assertEqual('security_group_rules', sot.resources_key) + self.assertEqual('/v2.0/security-group-rules', sot.base_path) + self.assertEqual('network', sot.service.service_type) + self.assertTrue(sot.allow_list) + self.assertTrue(sot.allow_create) + self.assertTrue(sot.allow_get) + self.assertFalse(sot.allow_update) + self.assertTrue(sot.allow_delete) + + def test_make_it(self): + sot = SecurityGroupRule(**EXAMPLE) + self.assertEqual(EXAMPLE['description'], sot.description) + self.assertEqual(EXAMPLE['direction'], sot.direction) + self.assertEqual(EXAMPLE['ethertype'], sot.ethertype) + self.assertEqual(EXAMPLE['id'], sot.id) + self.assertEqual(EXAMPLE['port_range_min'], sot.port_range_min) + self.assertEqual(EXAMPLE['port_range_max'], sot.port_range_max) + self.assertEqual(EXAMPLE['protocol'], sot.protocol) + self.assertEqual(EXAMPLE['remote_group_id'], sot.remote_group_id) + self.assertEqual(EXAMPLE['remote_ip_prefix'], sot.remote_ip_prefix) + self.assertEqual(EXAMPLE['security_group_id'], sot.security_group_id) + self.assertEqual(EXAMPLE['tenant_id'], sot.tenant_id) From 1cd42e974b8629f529448575fa7001db4664abdd Mon Sep 17 00:00:00 2001 From: shimisho <45929740+shimisho@users.noreply.github.com> Date: Mon, 9 May 2022 16:43:21 +0900 Subject: [PATCH 02/19] delete setup.cfg author-email (#108) * delete setup.cfg author-email * modified setup.cfg author-email From ca0fd2b3d8bffaba09ec84444cefd9fbf4c80694 Mon Sep 17 00:00:00 2001 From: shimisho <45929740+shimisho@users.noreply.github.com> Date: Tue, 10 May 2022 12:01:42 +0900 Subject: [PATCH 03/19] Delete author-email (#109) From d9fbb5dacca842c7d3c44394d109945fde429017 Mon Sep 17 00:00:00 2001 From: sugimo-s <91592177+sugimo-s@users.noreply.github.com> Date: Wed, 8 Jun 2022 16:21:13 +0900 Subject: [PATCH 04/19] :sparkles: IF-5247 Remove MSS v1 (#110) --- ecl/profile.py | 12 +- ecl/security_order_v1/__init__.py | 0 .../security_order_service.py | 14 - ecl/security_order_v1/v1/__init__.py | 0 ecl/security_order_v1/v1/_proxy.py | 444 ------------------ ecl/security_order_v1/v1/device.py | 114 ----- ecl/security_order_v1/v1/ha_device.py | 110 ----- .../v1/host_based_security.py | 97 ---- ecl/security_order_v1/v1/waf.py | 115 ----- ecl/security_portal_v1/__init__.py | 0 .../security_portal_service.py | 14 - ecl/security_portal_v1/v1/__init__.py | 0 ecl/security_portal_v1/v1/_proxy.py | 49 -- ecl/security_portal_v1/v1/security_device.py | 47 -- .../v1/security_device_interface.py | 49 -- 15 files changed, 1 insertion(+), 1064 deletions(-) delete mode 100755 ecl/security_order_v1/__init__.py delete mode 100755 ecl/security_order_v1/security_order_service.py delete mode 100755 ecl/security_order_v1/v1/__init__.py delete mode 100755 ecl/security_order_v1/v1/_proxy.py delete mode 100644 ecl/security_order_v1/v1/device.py delete mode 100644 ecl/security_order_v1/v1/ha_device.py delete mode 100644 ecl/security_order_v1/v1/host_based_security.py delete mode 100644 ecl/security_order_v1/v1/waf.py delete mode 100755 ecl/security_portal_v1/__init__.py delete mode 100755 ecl/security_portal_v1/security_portal_service.py delete mode 100755 ecl/security_portal_v1/v1/__init__.py delete mode 100755 ecl/security_portal_v1/v1/_proxy.py delete mode 100644 ecl/security_portal_v1/v1/security_device.py delete mode 100644 ecl/security_portal_v1/v1/security_device_interface.py diff --git a/ecl/profile.py b/ecl/profile.py index 9a489b6..23a510a 100755 --- a/ecl/profile.py +++ b/ecl/profile.py @@ -67,10 +67,6 @@ from ecl.storage import storage_service from ecl.security_order import security_order_service from ecl.security_portal import security_portal_service -## This section will be deleted if MSS v2 API is not available -from ecl.security_order_v2 import security_order_service as security_order_service_v2 -from ecl.security_portal_v2 import security_portal_service as security_portal_service_v2 -## end of the section from ecl.sss import sss_service from ecl.telemetry import telemetry_service from ecl.dns import dns_service @@ -114,13 +110,7 @@ def __init__(self, plugins=None): self._add_service( security_order_service.SecurityOrderService(version="v3")) self._add_service( - security_portal_service.SecurityPortalService(version="v3")) - ## This section will be deleted if MSS v2 API is not available - self._add_service( - security_order_service_v2.SecurityOrderService(version="v2")) - self._add_service( - security_portal_service_v2.SecurityPortalService(version="v2")) - ## end of the section + security_portal_service.SecurityPortalService(version="v2")) self._add_service(rca_service.RcaService(version="v1")) self._add_service(baremetal_service.BaremetalService(version="v2")) self._add_service( diff --git a/ecl/security_order_v1/__init__.py b/ecl/security_order_v1/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_order_v1/security_order_service.py b/ecl/security_order_v1/security_order_service.py deleted file mode 100755 index 8b5ddf6..0000000 --- a/ecl/security_order_v1/security_order_service.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl import service_filter - - -class SecurityOrderService(service_filter.ServiceFilter): - """The security service.""" - - valid_versions = [service_filter.ValidVersion('v1')] - - def __init__(self, version=None): - """Create a security service.""" - super(SecurityOrderService, self).__init__(service_type='mss-rfg', - version=version) diff --git a/ecl/security_order_v1/v1/__init__.py b/ecl/security_order_v1/v1/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_order_v1/v1/_proxy.py b/ecl/security_order_v1/v1/_proxy.py deleted file mode 100755 index 476864a..0000000 --- a/ecl/security_order_v1/v1/_proxy.py +++ /dev/null @@ -1,444 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v1.v1 import device as _fgs -from ecl.security_order_v1.v1 import ha_device as _fgha -from ecl.security_order_v1.v1 import waf as _fgwaf -from ecl.security_order_v1.v1 import host_based_security as _hbs -from ecl import proxy2 - - -class Proxy(proxy2.BaseProxy): - - def devices(self, locale=None): - """List Managed Firwall/UTM devices of single constitution. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v1.device.Device` - """ - fgs = _fgs.Device() - return fgs.list(self.session, locale=locale) - - def create_device(self, operatingmode, licensekind, - azgroup, locale=None): - """Create a new Managed Firewall/UTM device of single constitution. - - :param string operatingmode: Set "FW" or "UTM" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string azgroup: Availability Zone - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v1.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup - }] - body["sokind"] = "A" - if locale: - body["locale"] = locale - return self._create(_fgs.Device, **body) - - def update_device(self, hostname, operatingmode, - licensekind, locale=None): - """Change menu (Firewall/Managed UTM) and/or plan of single device. - - :param string operatingmode: Set "FW" or "UTM" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v1.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname, - "operatingmode": operatingmode, - "licensekind": licensekind - }] - body["sokind"] = "M" - if locale: - body.update({"locale": locale}) - fgs = _fgs.Device() - return fgs.update(self.session, **body) - - def delete_device(self, hostname, locale=None): - """Delete a Managed Firewall/UTM device of single constitution. - - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v1.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname - }] - body["sokind"] = "D" - if locale: - body["locale"] = locale - fgs = _fgs.Device() - return fgs.delete(self.session, body, locale=locale) - - def ha_devices(self, locale=None): - """List Managed Firwall/UTM devices of single constitution. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v1.ha_device.HADevice` - """ - fgha = _fgha.HADevice() - return fgha.list(self.session, locale=locale) - - def create_ha_device(self, operatingmode, licensekind, - azgroup1, azgroup2, - halink1networkid, halink1subnetid, - halink1ipaddress1, halink1ipaddress2, - halink2networkid, halink2subnetid, - halink2ipaddress1, halink2ipaddress2, - locale=None): - """Create a new Managed Firewall/UTM device of single constitution. - - :param string operatingmode: Set "UTM_HA" or "FW_HA" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string azgroup1: Availability Zone - :param string azgroup2: Availability Zone - :param string halink1networkid: Set Network ID to be used for HA line. - :param string halink1subnetid: Set Subnet ID to be used for HA line. - :param string halink1ipaddress1: Set value of IPv4. - :param string halink1ipaddress2: Set value of IPv4. - :param string halink2networkid: Set Network ID to be used for HA line. - :param string halink2subnetid: Set Subnet ID to be used for HA line. - :param string halink2ipaddress1: Set value of IPv4. - :param string halink2ipaddress2: Set value of IPv4. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v1.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup1, - "halink1networkid": halink1networkid, - "halink1subnetid": halink1subnetid, - "halink1ipaddress": halink1ipaddress1, - "halink2networkid": halink2networkid, - "halink2subnetid": halink2subnetid, - "halink2ipaddress": halink2ipaddress1 - },{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup2, - "halink1networkid": halink1networkid, - "halink1subnetid": halink1subnetid, - "halink1ipaddress": halink1ipaddress2, - "halink2networkid": halink2networkid, - "halink2subnetid": halink2subnetid, - "halink2ipaddress": halink2ipaddress2 - }] - body["sokind"] = "AH" - if locale: - body["locale"] = locale - return self._create(_fgha.HADevice, **body) - - def update_ha_device(self, hostname1, hostname2, operatingmode, - licensekind, locale=None): - """Change menu (Firewall/Managed UTM) and/or plan of single device. - - :param string hostname1: Set the hostname. - :param string hostname2: Set the hostname. - :param string operatingmode: Set "UTM_HA" or "FW_HA" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v1.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname1, - "operatingmode": operatingmode, - "licensekind": licensekind - },{ - "hostname": hostname2, - "operatingmode": operatingmode, - "licensekind": licensekind - }] - body["sokind"] = "MH" - if locale: - body.update({"locale": locale}) - fgha = _fgha.HADevice() - return fgha.update(self.session, **body) - - def delete_ha_device(self, hostname1, hostname2, locale=None): - """Delete a Managed Firewall/UTM device of single constitution. - - :param string hostname1: Set the hostname. - :param string hostname2: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v1.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname1 - }, { - "hostname": hostname2 - }] - body["sokind"] = "DH" - if locale: - body["locale"] = locale - fgha = _fgha.HADevice() - return fgha.delete(self.session, body, locale=locale) - - def get_device_order_status(self, soid, locale=None): - """Check progress status of Managed Firewall/UTM device Service Order. - - :param string soid: This value is returned value of when you execute - Create Server, Update Server or Delete Server API. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v1.device.Device` - """ - fgs = _fgs.Device() - return fgs.get_order_status(self.session, soid, locale=locale) - - def wafs(self, locale=None): - """List active waf devices you ordered. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v1.waf.WAF` - """ - fgwaf = _fgwaf.WAF() - return fgwaf.list(self.session, locale=locale) - - def create_waf(self, licensekind, azgroup, locale=None): - """Create a new WAF device. - - :param string licensekind: Set "02", "04" or "08" as WAF plan. - :param string azgroup: Availability Zone - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v1.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": "WAF", - "licensekind": licensekind, - "azgroup": azgroup - }] - body["sokind"] = "A" - if locale: - body["locale"] = locale - return self._create(_fgwaf.WAF, **body) - - def get_waf_order_status(self, soid, locale=None): - """Check progress status of Managed WAF device Service Order. - - :param string soid: This value is returned value of when you execute - Create Server, Update Server or Delete Server API. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v1.waf.WAF` - """ - fgwaf = _fgwaf.WAF() - return fgwaf.get_order_status(self.session, soid, locale=locale) - - def update_waf(self, hostname, licensekind, locale=None): - """Change plan of device. - - :param string licensekind: Set "02", "04" or "08" as WAF plan. - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v1.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname, - "licensekind": licensekind - }] - body["sokind"] = "M" - if locale: - body.update({"locale": locale}) - fgwaf = _fgwaf.WAF() - return fgwaf.update(self.session, **body) - - def delete_waf(self, hostname, locale=None): - """Delete a WAF device. - - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v1.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname - }] - body["sokind"] = "D" - if locale: - body["locale"] = locale - fgwaf = _fgwaf.WAF() - return fgwaf.delete(self.session, body, locale=locale) - - def get_hbs_order_status(self, soid, locale=None): - """Check progress status of Host-based Security Service Order. - - :param string soid: This value is returned value of when you execute API - of Order Host-based Security, Change menu or - quantity, or Cancel the order. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - hbs = _hbs.HostBasedSecurity() - return hbs.get_order_status(self.session, soid, locale=locale) - - def get_hbs_order_info(self, locale=None): - """Get Order Information that tied to tenant id. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - hbs = _hbs.HostBasedSecurity() - return hbs.get_order_info(self.session, locale=locale) - - def order_hbs(self, service_order_service, max_agent_value, - mailaddress, dsm_lang, time_zone, - locale=None): - """Make a new application for Host-based Security. - - :param string service_order_service: Requested menu. - Set "Managed Anti-Virus", "Managed Virtual Patch" - or "Managed Host-based Security Package" to this field. - :param string max_agent_value: Set maximum quantity of Agenet usage. - :param string mailaddress: Contactable mail address. - :param string dsm_lang: This value is used for language of Deep - Security Manager. ja: Japanese, en: English. - :param string time_zone: Set "Asia/Tokyo" for JST or "Etc/GMT" for UTC. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["service_order_service"] = service_order_service - body["max_agent_value"] = max_agent_value - body["mailaddress"] = mailaddress - body["dsm_lang"] = dsm_lang - body["time_zone"] = time_zone - body["sokind"] = "N" - if locale: - body["locale"] = locale - return self._create(_hbs.HostBasedSecurity, **body) - - def change_hbs_menu(self, service_order_service, mailaddress, locale=None): - """Change menu of Host-based Security. - - :param string service_order_service: Requested menu. - Set "Managed Anti-Virus", "Managed Virtual Patch" - or "Managed Host-based Security Package" to this field. - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["service_order_service"] = service_order_service - body["mailaddress"] = mailaddress - body["sokind"] = "M1" - if locale: - body.update({"locale": locale}) - hbs = _hbs.HostBasedSecurity() - return hbs.update(self.session, **body) - - def change_hbs_quantity(self, max_agent_value, mailaddress, locale=None): - """Change maximum quantity of Agent usage. - - :param string max_agent_value: Set maximum quantity of Agenet usage. - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["max_agent_value"] = max_agent_value - body["mailaddress"] = mailaddress - body["sokind"] = "M2" - if locale: - body.update({"locale": locale}) - hbs = _hbs.HostBasedSecurity() - return hbs.update(self.session, **body) - - def cancel_hbs(self, mailaddress, locale=None): - """Cancel the order of Host-based Security. - - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v1.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["mailaddress"] = mailaddress - body["sokind"] = "C" - if locale: - body["locale"] = locale - hbs = _hbs.HostBasedSecurity() - return hbs.delete(self.session, body, locale=locale) diff --git a/ecl/security_order_v1/v1/device.py b/ecl/security_order_v1/v1/device.py deleted file mode 100644 index da4d72f..0000000 --- a/ecl/security_order_v1/v1/device.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v1 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class Device(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGS' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "FW" or "UTM" to this value. - #: licensekind: Set "02" or "08" as FW/UTM plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGSOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGSDeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'hostname': row['cell'][2], - 'menu': row['cell'][3], - 'plan': row['cell'][4], - 'redundancy': row['cell'][5], - 'availability_zone': row['cell'][6], - 'zone_name': row['cell'][7], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_order_v1/v1/ha_device.py b/ecl/security_order_v1/v1/ha_device.py deleted file mode 100644 index 2e942d5..0000000 --- a/ecl/security_order_v1/v1/ha_device.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v1 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class HADevice(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGHA' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "FW" or "UTM" to this value. - #: licensekind: Set "02" or "08" as FW/UTM plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGHADeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'ha_id': row['cell'][2], - 'hostname': row['cell'][3], - 'menu': row['cell'][4], - 'plan': row['cell'][5], - 'redundancy': row['cell'][6], - 'availability_zone': row['cell'][7], - 'zone_name': row['cell'][8], - 'halink1networkid': row['cell'][9], - 'halink1subnetid': row['cell'][10], - 'halink1ipaddress': row['cell'][11], - 'halink2networkid': row['cell'][12], - 'halink2subnetid': row['cell'][13], - 'halink2ipaddress': row['cell'][14], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_order_v1/v1/host_based_security.py b/ecl/security_order_v1/v1/host_based_security.py deleted file mode 100644 index a5bc6eb..0000000 --- a/ecl/security_order_v1/v1/host_based_security.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v1 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - -class HostBasedSecurity(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryHBS' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: N: Order New Host-based Security. - #: M1: Change menu of Host-based Security. - #: M2: Change quantity of Host-based Security. - #: C: Cancel Host-based Security. - sokind = resource2.Body('sokind') - #: Requested menu. Set "Managed Anti-Virus", "Managed Virtual Patch" - #: or "Managed Host-based Security Package" to this field. - service_order_service = resource2.Body('service_order_service') - #: Set maximum quantity of Agenet usage. - max_agent_value = resource2.Body('max_agent_value') - #: Contactable mail address. - mailaddress = resource2.Body('mailaddress') - #: This value is used for language of Deep Security Manager. - #: ja: Japanese, en: English. - dsm_lang = resource2.Body('dsm_lang') - #: Set "Asia/Tokyo" for JST or "Etc/GMT" for UTC. - time_zone = resource2.Body('time_zone') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - #: Region tenant you specified belongs to. - region = resource2.Body('region') - #: Tenant Name. - tenant_name = resource2.Body('tenant_name') - #: Description for this tenant. - tenant_description = resource2.Body('tenant_description') - #: Contract ID which this tenant belongs to. - contract_id = resource2.Body('contract_id') - #: Customer Name. - customer_name = resource2.Body('customer_name') - #: Internal Use. (true: Already applied, false: Not applied.) - tenant_flg = resource2.Body('tenant_flg') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventHBSOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def get_order_info(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventHBSOrderInfoGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self diff --git a/ecl/security_order_v1/v1/waf.py b/ecl/security_order_v1/v1/waf.py deleted file mode 100644 index 9e8d53d..0000000 --- a/ecl/security_order_v1/v1/waf.py +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v1 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class WAF(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGWAF' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "WAF" to this value. - #: licensekind: Set "02", "04" or "08" as WAF plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - #: List of device objects. - devices = resource2.Body('devices') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGWAFOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGWAFDeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'hostname': row['cell'][2], - 'menu': row['cell'][3], - 'plan': row['cell'][4], - 'availability_zone': row['cell'][5], - 'zone_name': row['cell'][6], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_portal_v1/__init__.py b/ecl/security_portal_v1/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_portal_v1/security_portal_service.py b/ecl/security_portal_v1/security_portal_service.py deleted file mode 100755 index fc650f2..0000000 --- a/ecl/security_portal_v1/security_portal_service.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl import service_filter - - -class SecurityPortalService(service_filter.ServiceFilter): - """The security service.""" - - valid_versions = [service_filter.ValidVersion('v1')] - - def __init__(self, version=None): - """Create a security service.""" - super(SecurityPortalService, self).__init__(service_type='mss-msa', - version=version) diff --git a/ecl/security_portal_v1/v1/__init__.py b/ecl/security_portal_v1/v1/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_portal_v1/v1/_proxy.py b/ecl/security_portal_v1/v1/_proxy.py deleted file mode 100755 index 75c2d0d..0000000 --- a/ecl/security_portal_v1/v1/_proxy.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v1.v1 import security_device as _sd -from ecl.security_portal_v1.v1 import security_device_interface as _sdi -from ecl import proxy2 - - -class Proxy(proxy2.BaseProxy): - def security_devices(self): - """Listing security devices associated with specific tenant. - - :return: List security devices. - :rtype: :class:`~ecl.security_portal_v1.v1.security_device.SecurityDevice` - """ - return list(self._list(_sd.SecurityDevice, paginated=False, - tenantid=self.session.get_project_id(), - usertoken=self.session.get_token())) - - def get_security_device(self, server_id): - """Show security device details associated with specific tenant. - - :param string server_id: Server ID registered in Openstack(UUID). - :return: One security device. - :rtype: :class:`~ecl.security_portal_v1.v1.security_device.SecurityDevice` - """ - sd = _sd.SecurityDevice() - return sd.get(self.session, server_id) - - def security_device_interfaces(self, server_id): - """Listing security device Interfaces associated with specific tenant. - - :param string server_id: Server ID registered in Openstack(UUID). - :return: List security device interfaces. - :rtype: :class:`~ecl.security_portal_v1.v1.security_device_interface.SecurityDeviceInterface` - """ - return list(self._list(_sdi.SecurityDeviceInterface, paginated=False, - server_id=server_id, - tenantid=self.session.get_project_id(), - usertoken=self.session.get_token())) - - def get_security_device_interface(self, port_id): - """Show security device Interface associated with specific tenant. - - :param string port_id: Port ID registered in Openstack(UUID). - :return: One security device interface. - :rtype: :class:`~ecl.security_portal_v1.v1.security_device_interface.SecurityDeviceInterface` - """ - sdi = _sdi.SecurityDeviceInterface() - return sdi.get(self.session, port_id) diff --git a/ecl/security_portal_v1/v1/security_device.py b/ecl/security_portal_v1/v1/security_device.py deleted file mode 100644 index 618421e..0000000 --- a/ecl/security_portal_v1/v1/security_device.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v1 import security_portal_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class SecurityDevice(resource2.Resource): - resource_key = "device" - resources_key = "devices" - base_path = '/ecl-api/devices' - service = security_portal_service.SecurityPortalService() - - _query_mapping = resource2.QueryParameters( - "tenantid", - "usertoken", - ) - - # Capabilities - allow_get = True - allow_list = True - - # Properties - #: MSA Device External reference. - msa_device_id = resource2.Body('msa_device_id', alternate_id=True) - #: MSA Device Type. - msa_device_type = resource2.Body('msa_device_type') - #: Server id of Network-based Security devices. - os_server_id = resource2.Body('os_server_id') - #: Server name on Openstack. - os_server_name = resource2.Body('os_server_name') - #: Availability zone information. - os_availability_zone = resource2.Body('os_availability_zone') - #: Name of admin. - os_admin_username = resource2.Body('os_admin_username') - #: Server Status. - os_server_status = resource2.Body('os_server_status') - #: Interfaces details associated with the Security Device. - interfaces = resource2.Body('interfaces') - - def get(self, session, server_id): - uri = self.base_path + '/%s?tenantid=%s&usertoken=%s' \ - % (server_id, session.get_project_id(), session.get_token()) - resp = session.get(uri, endpoint_filter=self.service) - self._translate_response(resp, has_body=True) - return self diff --git a/ecl/security_portal_v1/v1/security_device_interface.py b/ecl/security_portal_v1/v1/security_device_interface.py deleted file mode 100644 index 227e497..0000000 --- a/ecl/security_portal_v1/v1/security_device_interface.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v1 import security_portal_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class SecurityDeviceInterface(resource2.Resource): - resource_key = "device_interface" - resources_key = "device_interfaces" - base_path = '/ecl-api/devices/%(server_id)s/interfaces' - service = security_portal_service.SecurityPortalService() - - _query_mapping = resource2.QueryParameters( - "tenantid", - "usertoken", - ) - - # Capabilities - allow_get = True - allow_list = True - - # Properties - #: Port id on Openstack. - os_port_id = resource2.Body('os_port_id', alternate_id=True) - #: Port IP address (if available). - os_ip_address = resource2.Body('os_ip_address') - #: Port id on the Network-based Security devices (registered in MSA). - msa_port_id = resource2.Body('msa_port_id') - #: Port name on Openstack. - os_port_name = resource2.Body('os_port_name') - #: Network Id to which Port is associated on Openstack. - os_network_id = resource2.Body('os_network_id') - #: Port Status on Openstack. - os_port_status = resource2.Body('os_port_status') - #: Port MAC address on Openstack. - os_mac_address = resource2.Body('os_mac_address') - #: Subnet Id to which Port is associated on Openstack. - os_subnet_id = resource2.Body('os_subnet_id') - #: Server id of Network-based Security devices. - os_server_id = resource2.Body('os_server_id') - - def get(self, session, port_id): - uri = '/ecl-api/devices/interface/%s?tenantid=%s&usertoken=%s' \ - % (port_id, session.get_project_id(), session.get_token()) - resp = session.get(uri, endpoint_filter=self.service) - self._translate_response(resp, has_body=True) - return self From 6f111e965c46187d80e13b1b85c29a733351e86c Mon Sep 17 00:00:00 2001 From: Yoshiki Kashiwabara <91601085+KashiwabaraY@users.noreply.github.com> Date: Wed, 5 Oct 2022 14:27:04 +0900 Subject: [PATCH 05/19] :sparkles: IF-7320 add smb_propaerties to storage (#120) (#123) * :sparkles: IF-7320 add smb_propaerties to storage * :sparkles: IF-7320 add smb_propaerties to storage Co-authored-by: Yoshiki Kashiwabara Co-authored-by: Yoshiki Kashiwabara --- ecl/storage/v1/storage.py | 3 ++- ecl/storage/v1/volume.py | 2 ++ ecl/tests/unit/storage/v1/test_storage.py | 8 ++++++++ ecl/tests/unit/storage/v1/test_volume.py | 10 +++++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ecl/storage/v1/storage.py b/ecl/storage/v1/storage.py index 431e35e..515a0ad 100755 --- a/ecl/storage/v1/storage.py +++ b/ecl/storage/v1/storage.py @@ -14,7 +14,6 @@ from ecl.storage import storage_service from ecl import resource2 -from ecl.storage import storage_service class Storage(resource2.Resource): @@ -56,6 +55,8 @@ class Storage(resource2.Resource): updated_at = resource2.Body('updated_at') #: error description of storage error_message = resource2.Body('error_message') + #: properties for smb storage + smb_properties = resource2.Body('smb_properties', type=dict) def create(self, session, **attrs): body = {"virtual_storage": attrs} diff --git a/ecl/storage/v1/volume.py b/ecl/storage/v1/volume.py index f8e3f6d..6b8a997 100755 --- a/ecl/storage/v1/volume.py +++ b/ecl/storage/v1/volume.py @@ -73,6 +73,8 @@ class Volume(resource2.Resource): #: Percentage of Used Snapshots percentage_snapshot_reserve_used = \ resource2.Body('percentage_snapshot_reserve_used', type=int) + #: properties for smb storage + smb_properties = resource2.Body('smb_properties', type=dict) def create(self, session, **attrs): body = {"volume":attrs} diff --git a/ecl/tests/unit/storage/v1/test_storage.py b/ecl/tests/unit/storage/v1/test_storage.py index 8281da1..5af9ef8 100755 --- a/ecl/tests/unit/storage/v1/test_storage.py +++ b/ecl/tests/unit/storage/v1/test_storage.py @@ -34,6 +34,13 @@ 'created_at': 'null', 'updated_at': 'null', 'error_message': '', + 'smb_properties': { + 'workgroup': 'WORKGROUP', + 'users': [{ + 'username': 'testuser', + 'password': '#pass1234', + }, ], + }, } @@ -77,3 +84,4 @@ def test_make_basic(self): self.assertEqual(BASIC_EXAMPLE['created_at'], sot.created_at) self.assertEqual(BASIC_EXAMPLE['updated_at'], sot.updated_at) self.assertEqual(BASIC_EXAMPLE['error_message'], sot.error_message) + self.assertEqual(BASIC_EXAMPLE['smb_properties'], sot.smb_properties) diff --git a/ecl/tests/unit/storage/v1/test_volume.py b/ecl/tests/unit/storage/v1/test_volume.py index 753d426..45126f0 100755 --- a/ecl/tests/unit/storage/v1/test_volume.py +++ b/ecl/tests/unit/storage/v1/test_volume.py @@ -34,7 +34,14 @@ 'updated_at': 'null', 'error_message': '', 'throughput': 50, - 'export_rules': [] + 'export_rules': [], + 'smb_properties': { + 'workgroup': 'WORKGROUP', + 'users': [{ + 'username': 'testuser', + 'password': '#pass1234', + }, ], + }, } @@ -85,3 +92,4 @@ def test_make_basic(self): self.assertEqual(BASIC_EXAMPLE['error_message'], sot.error_message) self.assertEqual(BASIC_EXAMPLE['throughput'], sot.throughput) self.assertEqual(BASIC_EXAMPLE['export_rules'], sot.export_rules) + self.assertEqual(BASIC_EXAMPLE['smb_properties'], sot.smb_properties) From dccbc055a536df23cb616bb51d8eef00bebf0dea Mon Sep 17 00:00:00 2001 From: akaishizawa-n <135296314+akaishizawa-n@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:39:48 +0900 Subject: [PATCH 06/19] :sparkles: Implement volume retype support IF-14543 (#174) (#177) --- ecl/compute/v2/_proxy.py | 17 +++++++++++++++-- ecl/compute/v2/server.py | 7 ++++--- ecl/compute/v2/volume.py | 26 ++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ecl/compute/v2/_proxy.py b/ecl/compute/v2/_proxy.py index 95d7646..f6b5e7c 100755 --- a/ecl/compute/v2/_proxy.py +++ b/ecl/compute/v2/_proxy.py @@ -227,16 +227,17 @@ def stop_server(self, server): virtual_server = self.get_server(server) return virtual_server.stop(self.session) - def resize_server(self, server, flavor_id): + def resize_server(self, server, flavor_id, is_dry_run=False): """Resize the server to flavor reference :param server: Either the ID of a server or a :class:`~ecl.compute.v2.server.Server` instance. :param string flavor_id: ID of flavor to resize + :param bool is_dry_run:When set to "True" will enable dry run mode. :return: """ virtual_server = self.get_server(server) - return virtual_server.resize(self.session, flavor_id) + return virtual_server.resize(self.session, flavor_id, is_dry_run) def get_server_metadata(self, server): """Return a dictionary of metadata for a server @@ -816,3 +817,15 @@ def delete_volume(self, volume, ignore_missing=False): :returns: ``None`` """ self._delete(_volume.Volume, volume, ignore_missing=ignore_missing) + + def retype_volume(self, volume, volume_type, is_dry_run=False): + """Retype an volume + + :param volume:The value can be either the ID of an volume or a + :class:`~ecl.compute.v2.volume.Volume` instance. + :param volume_type: volume type of volume to retype. + :param bool is_dry_run:When set to "True" will enable dry run mode. + :returns: + """ + volume_obj = self.get_volume(volume) + return volume_obj.retype(self.session, volume_type, is_dry_run) diff --git a/ecl/compute/v2/server.py b/ecl/compute/v2/server.py index aa81ab9..9950229 100755 --- a/ecl/compute/v2/server.py +++ b/ecl/compute/v2/server.py @@ -204,14 +204,15 @@ def stop(self, session): body = {"os-stop": None} return self._action(session, body) - def resize(self, session, flavor): + def resize(self, session, flavor, is_dry_run=False): """Resize server to flavor reference.""" body = { 'resize': { - 'flavorRef': flavor, - 'OS-DCF:diskConfig': 'AUTO' + 'flavorRef': flavor } } + if is_dry_run: + body['resize']['dryRun'] = True self._action(session, body) def change_password(self, session, new_password): diff --git a/ecl/compute/v2/volume.py b/ecl/compute/v2/volume.py index e148fbe..e642b5b 100755 --- a/ecl/compute/v2/volume.py +++ b/ecl/compute/v2/volume.py @@ -2,12 +2,12 @@ from ecl.compute import compute_service from ecl import resource2 - +from ecl import utils class Volume(resource2.Resource): resource_key = 'volume' resources_key = 'volumes' - base_path = '/os-volumes' + base_path = '/volumes' service = compute_service.ComputeService() # capabilities @@ -30,6 +30,28 @@ class Volume(resource2.Resource): status = resource2.Body('status') bootable = resource2.Body('bootable') + def retype(self, session, volume_type, is_dry_run=False): + """ Volume type change and dry run configuration process. """ + body = { + 'os-retype': { + 'new_type': volume_type, + 'migration_policy': 'on-demand' + } + } + if is_dry_run: + body['os-retype']['dryRun'] = True + self._action(session, body) + + def _action(self, session, body): + """Preform server actions given the message body.""" + # NOTE: This is using Server.base_path instead of self.base_path + # as both Server and ServerDetail instances can be acted on, but + # the URL used is sans any additional /detail/ part. + url = utils.urljoin(Volume.base_path, self.id, 'action') + headers = {'Accept': ''} + return session.post( + url, endpoint_filter=self.service, json=body, headers=headers) + class VolumeDetail(Volume): base_path = '/os-volumes/detail' From 24351078ad0aeb44279f63ec86b661c134b091d5 Mon Sep 17 00:00:00 2001 From: akaishizawa-n <135296314+akaishizawa-n@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:48:42 +0900 Subject: [PATCH 07/19] Dev/volume retype (#180) * :bug: IF-15594 Fix service type for Volume class (#179) --- ecl/block_store/v2/_proxy.py | 12 ++++++++++++ ecl/block_store/v2/volume.py | 12 ++++++++++++ ecl/compute/v2/_proxy.py | 12 ------------ ecl/compute/v2/volume.py | 25 +------------------------ 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/ecl/block_store/v2/_proxy.py b/ecl/block_store/v2/_proxy.py index 24bb2fd..350ac18 100755 --- a/ecl/block_store/v2/_proxy.py +++ b/ecl/block_store/v2/_proxy.py @@ -179,6 +179,18 @@ def update_bootable(self, volume, bootable=False): volume = self._get_resource(_volume.Volume, volume) return volume.update_bootable(self.session, bootable) + def retype_volume(self, volume, volume_type, is_dry_run=False): + """Retype an volume + + :param volume:The value can be either the ID of an volume or a + :class:`~ecl.compute.v2.volume.Volume` instance. + :param volume_type: volume type of volume to retype. + :param bool is_dry_run:When set to "True" will enable dry run mode. + :returns: + """ + volume = self._get_resource(_volume.Volume, volume) + return volume.retype(self.session, volume_type, is_dry_run) + def availability_zones(self): """Return a list of availability zones diff --git a/ecl/block_store/v2/volume.py b/ecl/block_store/v2/volume.py index d1fa630..b6a6d21 100755 --- a/ecl/block_store/v2/volume.py +++ b/ecl/block_store/v2/volume.py @@ -107,6 +107,18 @@ def update_bootable(self, session, bootable=False): }} return self._action(session, body) + def retype(self, session, volume_type, is_dry_run=False): + """ Volume type change and dry run configuration process. """ + body = { + 'os-retype': { + 'new_type': volume_type, + 'migration_policy': 'on-demand' + } + } + if is_dry_run: + body['os-retype']['dryRun'] = True + self._action(session, body) + class VolumeDetail(Volume): diff --git a/ecl/compute/v2/_proxy.py b/ecl/compute/v2/_proxy.py index f6b5e7c..7a1d48c 100755 --- a/ecl/compute/v2/_proxy.py +++ b/ecl/compute/v2/_proxy.py @@ -817,15 +817,3 @@ def delete_volume(self, volume, ignore_missing=False): :returns: ``None`` """ self._delete(_volume.Volume, volume, ignore_missing=ignore_missing) - - def retype_volume(self, volume, volume_type, is_dry_run=False): - """Retype an volume - - :param volume:The value can be either the ID of an volume or a - :class:`~ecl.compute.v2.volume.Volume` instance. - :param volume_type: volume type of volume to retype. - :param bool is_dry_run:When set to "True" will enable dry run mode. - :returns: - """ - volume_obj = self.get_volume(volume) - return volume_obj.retype(self.session, volume_type, is_dry_run) diff --git a/ecl/compute/v2/volume.py b/ecl/compute/v2/volume.py index e642b5b..9a5d19e 100755 --- a/ecl/compute/v2/volume.py +++ b/ecl/compute/v2/volume.py @@ -2,12 +2,11 @@ from ecl.compute import compute_service from ecl import resource2 -from ecl import utils class Volume(resource2.Resource): resource_key = 'volume' resources_key = 'volumes' - base_path = '/volumes' + base_path = '/os-volumes' service = compute_service.ComputeService() # capabilities @@ -30,28 +29,6 @@ class Volume(resource2.Resource): status = resource2.Body('status') bootable = resource2.Body('bootable') - def retype(self, session, volume_type, is_dry_run=False): - """ Volume type change and dry run configuration process. """ - body = { - 'os-retype': { - 'new_type': volume_type, - 'migration_policy': 'on-demand' - } - } - if is_dry_run: - body['os-retype']['dryRun'] = True - self._action(session, body) - - def _action(self, session, body): - """Preform server actions given the message body.""" - # NOTE: This is using Server.base_path instead of self.base_path - # as both Server and ServerDetail instances can be acted on, but - # the URL used is sans any additional /detail/ part. - url = utils.urljoin(Volume.base_path, self.id, 'action') - headers = {'Accept': ''} - return session.post( - url, endpoint_filter=self.service, json=body, headers=headers) - class VolumeDetail(Volume): base_path = '/os-volumes/detail' From 3beb0489ec8bc6fb32c9db6464c58115654432dd Mon Sep 17 00:00:00 2001 From: Yoshiki Kashiwabara <91601085+KashiwabaraY@users.noreply.github.com> Date: Fri, 4 Jul 2025 10:20:37 +0900 Subject: [PATCH 08/19] :sparkles: Add vna allocation IF-14793 (#178) (#181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 柏原由己 --- ecl/virtual_network_appliance/v1/_proxy.py | 11 +++++++++++ .../v1/virtual_network_appliance.py | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/ecl/virtual_network_appliance/v1/_proxy.py b/ecl/virtual_network_appliance/v1/_proxy.py index 8305e30..bfefce2 100755 --- a/ecl/virtual_network_appliance/v1/_proxy.py +++ b/ecl/virtual_network_appliance/v1/_proxy.py @@ -305,3 +305,14 @@ def find_virtual_network_appliance_plan(self, name_or_id, _virtual_network_appliance_plan.VirtualNetworkAppliancePlan, name_or_id, ignore_missing=ignore_missing) + + def reallocate_virtual_network_appliance(self, virtual_network_appliance): + """Reallocate the virtual network appliance. + + :param virtual_network_appliance: + The ID of a virtual network appliance. + :return: + """ + virtual_network_appliance = \ + self.get_virtual_network_appliance(virtual_network_appliance) + return virtual_network_appliance.reallocate(self.session) diff --git a/ecl/virtual_network_appliance/v1/virtual_network_appliance.py b/ecl/virtual_network_appliance/v1/virtual_network_appliance.py index e129c25..b09c4ed 100755 --- a/ecl/virtual_network_appliance/v1/virtual_network_appliance.py +++ b/ecl/virtual_network_appliance/v1/virtual_network_appliance.py @@ -64,6 +64,8 @@ class VirtualNetworkAppliance(base.VirtualNetworkApplianceBaseResource): new_password = resource2.Body('new_password') #: Initial config of virtual network appliance. initial_config = resource2.Body('initial_config') + #: Reallocation status of virtual network appliance + reallocation_needed = resource2.Body('reallocation_needed') def update(self, session, prepend_key=True, has_body=True): """Update the remote resource based on this virtual network appliance. @@ -136,3 +138,8 @@ def get_console(self, session, vnc_type): console_dict = resp.json() if console_dict: return console_dict.get("console") + + def reallocate(self, session): + """Reallocate virtual network appliance""" + body = {'reallocate': None} + self._action(session, body) From f03fb1b8df9d9380946760fe59411c668a56bb5f Mon Sep 17 00:00:00 2001 From: akaishizawa-n <135296314+akaishizawa-n@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:34:01 +0900 Subject: [PATCH 09/19] :bug: Fix added japanese translation for volume list status IF-15753 (#185) --- ecl/block_store/v2/volume.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecl/block_store/v2/volume.py b/ecl/block_store/v2/volume.py index b6a6d21..8458e8b 100755 --- a/ecl/block_store/v2/volume.py +++ b/ecl/block_store/v2/volume.py @@ -116,7 +116,7 @@ def retype(self, session, volume_type, is_dry_run=False): } } if is_dry_run: - body['os-retype']['dryRun'] = True + body['os-retype']['dry_run'] = True self._action(session, body) From 2921d2ded981ef9cdaeb4f5122ba54a4cc336310 Mon Sep 17 00:00:00 2001 From: MikuInoueTx Date: Wed, 22 Oct 2025 17:32:49 +0900 Subject: [PATCH 10/19] :sparkles: IF-15429 Support vThunder ADC (#195) (#196) --- ecl/virtual_network_appliance/v1/virtual_network_appliance.py | 3 +-- .../v1/virtual_network_appliance_plan.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ecl/virtual_network_appliance/v1/virtual_network_appliance.py b/ecl/virtual_network_appliance/v1/virtual_network_appliance.py index b09c4ed..44fc784 100755 --- a/ecl/virtual_network_appliance/v1/virtual_network_appliance.py +++ b/ecl/virtual_network_appliance/v1/virtual_network_appliance.py @@ -23,8 +23,7 @@ class VirtualNetworkAppliance(base.VirtualNetworkApplianceBaseResource): allow_update = True allow_delete = True - # _query_mapping = resource2.QueryParameters() - # TBD + _query_mapping = resource2.QueryParameters("appliance_type") # Properties #: It identifies connection resource uniquely. diff --git a/ecl/virtual_network_appliance/v1/virtual_network_appliance_plan.py b/ecl/virtual_network_appliance/v1/virtual_network_appliance_plan.py index ea51489..5c5c8cf 100755 --- a/ecl/virtual_network_appliance/v1/virtual_network_appliance_plan.py +++ b/ecl/virtual_network_appliance/v1/virtual_network_appliance_plan.py @@ -16,7 +16,7 @@ class VirtualNetworkAppliancePlan(base.VirtualNetworkApplianceBaseResource): allow_list = True allow_get = True - _query_mapping = resource2.QueryParameters("details") + _query_mapping = resource2.QueryParameters("details", "appliance_type") # Properties #: It identifies connection resource uniquely. From 74216a7c5766325794625549462a01f6924b84ff Mon Sep 17 00:00:00 2001 From: t-yokoix Date: Tue, 4 Nov 2025 09:24:40 +0900 Subject: [PATCH 11/19] =?UTF-8?q?=E2=9C=A8=20Support=20Block=20storage=20G?= =?UTF-8?q?en2=20IF-16696=20(#198)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :sparkles: IF-16696 Block storage Gen2: Add parameter to Volume API --- ecl/storage/v1/_proxy.py | 5 +- ecl/storage/v1/volume.py | 6 ++ .../functional/storage/v1/test_volume.py | 100 ++++++++++++------ ecl/tests/unit/storage/v1/test_volume.py | 6 ++ 4 files changed, 82 insertions(+), 35 deletions(-) diff --git a/ecl/storage/v1/_proxy.py b/ecl/storage/v1/_proxy.py index e056802..aa3ff4e 100755 --- a/ecl/storage/v1/_proxy.py +++ b/ecl/storage/v1/_proxy.py @@ -211,7 +211,7 @@ def get_volume(self, volume_id): def create_volume(self, virtual_storage_id, name, size, description=None, iops_per_gb=None, initiator_iqns=None, throughput=None, - availability_zone=None): + availability_zone=None, snapshot_reserve_size=None): """This API create additional Volume. :param virtual_storage_id: Virtual Storage ID. @@ -222,6 +222,7 @@ def create_volume(self, virtual_storage_id, name, size, description=None, :param throughput: Provisioned throughput for volume. :param initiator_iqns: List of initiator IQN who can access to this volume. :param availability_zone: Availability zone. + :param snapshot_reserve_size: Size of Snapshot Reserve :return: :class:`~ecl.storage.v1.volume.Volume` """ body = {"virtual_storage_id": virtual_storage_id, "name": name, "size": size} @@ -235,6 +236,8 @@ def create_volume(self, virtual_storage_id, name, size, description=None, body["initiator_iqns"] = initiator_iqns if availability_zone: body["availability_zone"] = availability_zone + if snapshot_reserve_size: + body["snapshot_reserve_size"] = snapshot_reserve_size volume = _volume.Volume() return volume.create(self.session, **body) diff --git a/ecl/storage/v1/volume.py b/ecl/storage/v1/volume.py index 6b8a997..399e368 100755 --- a/ecl/storage/v1/volume.py +++ b/ecl/storage/v1/volume.py @@ -73,6 +73,12 @@ class Volume(resource2.Resource): #: Percentage of Used Snapshots percentage_snapshot_reserve_used = \ resource2.Body('percentage_snapshot_reserve_used', type=int) + #: The size of Snapshots Reserve + snapshot_reserve_size = \ + resource2.Body('snapshot_reserve_size', type=int) + #: The size of Used Snapshots Reserve + snapshot_reserve_used = \ + resource2.Body('snapshot_reserve_used', type=int) #: properties for smb storage smb_properties = resource2.Body('smb_properties', type=dict) diff --git a/ecl/tests/functional/storage/v1/test_volume.py b/ecl/tests/functional/storage/v1/test_volume.py index cf62554..197068f 100755 --- a/ecl/tests/functional/storage/v1/test_volume.py +++ b/ecl/tests/functional/storage/v1/test_volume.py @@ -12,6 +12,7 @@ import six import time + from ecl.tests.functional import base @@ -19,37 +20,51 @@ class TestVolume(base.BaseFunctionalTest): def test_01_volumes(self): volumes = list(self.conn.storage.volumes(details=True)) volume = volumes[1] + self.assertIsInstance(volume.id, six.string_types) - self.assertIsInstance(volume.status, six.string_types) self.assertIsInstance(volume.name, six.string_types) - self.assertIsInstance(volume.size, int) self.assertIsInstance(volume.description, six.string_types) - self.assertIsInstance(volume.iops_per_gb, six.string_types) - self.assertIsInstance(volume.initiator_iqns, list) - self.assertIsInstance(volume.target_ips, list) - self.assertIsInstance(volume.metadata, dict) self.assertIsInstance(volume.virtual_storage_id, six.string_types) + self.assertIsInstance(volume.status, six.string_types) + self.assertIsInstance(volume.size, six.integer_types) + self.assertIsNone(volume.created_at) + self.assertIsNone(volume.updated_at) + self.assertIsInstance(volume.error_message, six.string_types) + self.assertIsInstance(volume.target_ips, list) self.assertIsInstance(volume.availability_zone, six.string_types) - self.assertIsInstance(volume.created_at, six.string_types) - self.assertIsInstance(volume.updated_at, six.string_types) - self.assertIsInstance(volume.id, six.string_types) + self.assertIsInstance(volume.snapshot_ids, list) + self.assertIsInstance(volume.iops_per_gb, six.integer_types) + self.assertIsInstance(volume.initiator_iqns, list) + self.assertIsNone(volume.initiator_secret) + self.assertIsNone(volume.target_secret) + self.assertIsInstance(volume.metadata, dict) + self.assertIsInstance(volume.percentage_snapshot_reserve_used, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_size, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_used, six.integer_types) def test_02_show_volume(self): volume = self.conn.storage.get_volume("4096336b-7035-412a-8148-ad999f0e0bc8") + self.assertIsInstance(volume.id, six.string_types) - self.assertIsInstance(volume.status, six.string_types) self.assertIsInstance(volume.name, six.string_types) - self.assertIsInstance(volume.size, int) self.assertIsInstance(volume.description, six.string_types) - self.assertIsInstance(volume.iops_per_gb, six.string_types) - self.assertIsInstance(volume.initiator_iqns, list) - self.assertIsInstance(volume.target_ips, list) - self.assertIsInstance(volume.metadata, dict) self.assertIsInstance(volume.virtual_storage_id, six.string_types) + self.assertIsInstance(volume.status, six.string_types) + self.assertIsInstance(volume.size, six.integer_types) + self.assertIsNone(volume.created_at) + self.assertIsNone(volume.updated_at) + self.assertIsInstance(volume.error_message, six.string_types) + self.assertIsInstance(volume.target_ips, list) self.assertIsInstance(volume.availability_zone, six.string_types) - self.assertIsInstance(volume.created_at, six.string_types) - self.assertIsInstance(volume.updated_at, six.string_types) - self.assertIsInstance(volume.id, six.string_types) + self.assertIsInstance(volume.snapshot_ids, list) + self.assertIsInstance(volume.iops_per_gb, six.integer_types) + self.assertIsInstance(volume.initiator_iqns, list) + self.assertIsNone(volume.initiator_secret) + self.assertIsNone(volume.target_secret) + self.assertIsInstance(volume.metadata, dict) + self.assertIsInstance(volume.percentage_snapshot_reserve_used, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_size, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_used, six.integer_types) def test_03_update_volume(self): volume = self.conn.storage.update_volume( @@ -57,20 +72,27 @@ def test_03_update_volume(self): description="updated_test" ) print(volume.description) + self.assertIsInstance(volume.id, six.string_types) - self.assertIsInstance(volume.status, six.string_types) self.assertIsInstance(volume.name, six.string_types) - self.assertIsInstance(volume.size, int) self.assertIsInstance(volume.description, six.string_types) - self.assertIsInstance(volume.iops_per_gb, six.string_types) - self.assertIsInstance(volume.initiator_iqns, list) - self.assertIsInstance(volume.target_ips, list) - self.assertIsInstance(volume.metadata, dict) self.assertIsInstance(volume.virtual_storage_id, six.string_types) + self.assertIsInstance(volume.status, six.string_types) + self.assertIsInstance(volume.size, six.integer_types) + self.assertIsNone(volume.created_at) + self.assertIsNone(volume.updated_at) + self.assertIsInstance(volume.error_message, six.string_types) + self.assertIsInstance(volume.target_ips, list) self.assertIsInstance(volume.availability_zone, six.string_types) - self.assertIsInstance(volume.created_at, six.string_types) - self.assertIsInstance(volume.updated_at, six.string_types) - self.assertIsInstance(volume.id, six.string_types) + self.assertIsInstance(volume.snapshot_ids, list) + self.assertIsInstance(volume.iops_per_gb, six.integer_types) + self.assertIsInstance(volume.initiator_iqns, list) + self.assertIsNone(volume.initiator_secret) + self.assertIsNone(volume.target_secret) + self.assertIsInstance(volume.metadata, dict) + self.assertIsInstance(volume.percentage_snapshot_reserve_used, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_size, six.integer_types) + self.assertIsInstance(volume.snapshot_reserve_used, six.integer_types) @classmethod def test_04_create_volume(cls): @@ -79,18 +101,28 @@ def test_04_create_volume(cls): size=100, virtual_storage_id="19ff4cba-3b86-4da1-9663-25ea74f9b0a9", ) + assert isinstance(volume.id, six.string_types) - assert isinstance(volume.status, six.string_types) assert isinstance(volume.name, six.string_types) - assert isinstance(volume.size, int) assert isinstance(volume.description, six.string_types) - assert isinstance(volume.iops_per_gb, six.string_types) - assert isinstance(volume.initiator_iqns, list) - assert isinstance(volume.target_ips, list) - assert isinstance(volume.metadata, dict) assert isinstance(volume.virtual_storage_id, six.string_types) + assert isinstance(volume.status, six.string_types) + assert isinstance(volume.size, six.integer_types) + assert volume.created_at is None + assert volume.updated_at is None + assert isinstance(volume.error_message, six.string_types) + assert isinstance(volume.target_ips, list) assert isinstance(volume.availability_zone, six.string_types) - assert isinstance(volume.created_at, six.string_types) + assert isinstance(volume.snapshot_ids, list) + assert isinstance(volume.iops_per_gb, six.integer_types) + assert isinstance(volume.initiator_iqns, list) + assert volume.initiator_secret is None + assert volume.target_secret is None + assert isinstance(volume.metadata, dict) + assert isinstance(volume.percentage_snapshot_reserve_used, six.integer_types) + assert isinstance(volume.snapshot_reserve_size, six.integer_types) + assert isinstance(volume.snapshot_reserve_used, six.integer_types) + cls.vol_id = volume.id def test_05_delete_volume(self): diff --git a/ecl/tests/unit/storage/v1/test_volume.py b/ecl/tests/unit/storage/v1/test_volume.py index 45126f0..2667e4f 100755 --- a/ecl/tests/unit/storage/v1/test_volume.py +++ b/ecl/tests/unit/storage/v1/test_volume.py @@ -35,6 +35,9 @@ 'error_message': '', 'throughput': 50, 'export_rules': [], + 'percentage_snapshot_reserve_used': 50, + 'snapshot_reserve_size': 12, + 'snapshot_reserve_used': 6, 'smb_properties': { 'workgroup': 'WORKGROUP', 'users': [{ @@ -93,3 +96,6 @@ def test_make_basic(self): self.assertEqual(BASIC_EXAMPLE['throughput'], sot.throughput) self.assertEqual(BASIC_EXAMPLE['export_rules'], sot.export_rules) self.assertEqual(BASIC_EXAMPLE['smb_properties'], sot.smb_properties) + self.assertEqual(BASIC_EXAMPLE['percentage_snapshot_reserve_used'], sot.percentage_snapshot_reserve_used) + self.assertEqual(BASIC_EXAMPLE['snapshot_reserve_size'], sot.snapshot_reserve_size) + self.assertEqual(BASIC_EXAMPLE['snapshot_reserve_used'], sot.snapshot_reserve_used) From f4c06e687dbb55c4e1f041b19d02604d31e1ce99 Mon Sep 17 00:00:00 2001 From: t-yokoix Date: Wed, 12 Nov 2025 09:04:28 +0900 Subject: [PATCH 12/19] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Process=20to=20check?= =?UTF-8?q?=20param=20for=20Block=20storage=20Gen2=20IF-16696=20(#199)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :bug: IF-16696 Fix null check variables to create volume api --- ecl/storage/v1/_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecl/storage/v1/_proxy.py b/ecl/storage/v1/_proxy.py index aa3ff4e..a887d1e 100755 --- a/ecl/storage/v1/_proxy.py +++ b/ecl/storage/v1/_proxy.py @@ -236,7 +236,7 @@ def create_volume(self, virtual_storage_id, name, size, description=None, body["initiator_iqns"] = initiator_iqns if availability_zone: body["availability_zone"] = availability_zone - if snapshot_reserve_size: + if snapshot_reserve_size is not None: body["snapshot_reserve_size"] = snapshot_reserve_size volume = _volume.Volume() return volume.create(self.session, **body) From a9896c81200c8bcc4d9eee8f66d2473cb1fa23b6 Mon Sep 17 00:00:00 2001 From: sugimo-s <91592177+sugimo-s@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:30:37 +0900 Subject: [PATCH 13/19] Dev/lbs vthunder (#204) * :sparkles: Add request path parameter for operation IF-17033 (#202) --- ecl/virtual_network_appliance/v1/operation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ecl/virtual_network_appliance/v1/operation.py b/ecl/virtual_network_appliance/v1/operation.py index ead9b1d..f7b81f8 100755 --- a/ecl/virtual_network_appliance/v1/operation.py +++ b/ecl/virtual_network_appliance/v1/operation.py @@ -30,6 +30,8 @@ class Operation(base.VirtualNetworkApplianceBaseResource): reception_datetime = resource2.Body('reception_datetime') #: Commit datetime of operation. commit_datetime = resource2.Body('commit_datetime') + #: Request path of operation. + request_path = resource2.Body('request_path') #: Request body(JSON String) of operation. request_body = resource2.Body('request_body') #: Warning of operation. From 98eabae0f9aec9ae4cb5becf83d5f8ffdbe4e28b Mon Sep 17 00:00:00 2001 From: sugimo-s <91592177+sugimo-s@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:07:26 +0900 Subject: [PATCH 14/19] :bug: Fixed to display the error message of API response IF-17111 (#205) --- ecl/virtual_network_appliance/exceptions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ecl/virtual_network_appliance/exceptions.py b/ecl/virtual_network_appliance/exceptions.py index 215ec21..acd78d8 100755 --- a/ecl/virtual_network_appliance/exceptions.py +++ b/ecl/virtual_network_appliance/exceptions.py @@ -9,7 +9,7 @@ class HttpException(exceptions.HttpException): def _get_exception_message(self, message=None): try: - content = json.loads(self.response._content) + content = json.loads(self.response._content.decode('utf-8')) # API-GW if 'fault' in content and 'faultstring' in content['fault']: @@ -21,7 +21,7 @@ def _get_exception_message(self, message=None): # In VNA API, we need to handle both "cause" and "message" key # as API error. - k = content.keys() + k = list(content.keys()) if 'message' in k and 'cause' not in k: return content['message'] if 'cause' in k and 'message' not in k: From de06aa51ef2b29a5f0e9740c33436677435a28b0 Mon Sep 17 00:00:00 2001 From: MikuInoueTx Date: Wed, 25 Feb 2026 09:29:28 +0900 Subject: [PATCH 15/19] :sparkles: IF-17146 Support Update BMC Password (#209) (#210) --- ecl/baremetal/v2/_proxy.py | 12 +++++++++++ ecl/baremetal/v2/server.py | 15 +++++++++++++ .../baremetal/test_server_action.py | 21 +++++++++++-------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/ecl/baremetal/v2/_proxy.py b/ecl/baremetal/v2/_proxy.py index 41fdc3c..33ff91d 100755 --- a/ecl/baremetal/v2/_proxy.py +++ b/ecl/baremetal/v2/_proxy.py @@ -467,6 +467,18 @@ def reset_bmc(self, server_id, type): server = _server.ServerAction() return server.reset_bmc(self.session, server_id, type) + def update_bmc_password(self, server_id, password): + """Update the password for the Baseboard Management Controller + of the Baremetal Server associated with server_id. + This request will be accepted only when the task_state is None. + + :param string server_id: ID for the server. + :param string password: New password for BMC. + :return: ``None`` + """ + server = _server.ServerAction() + return server.update_bmc_password(self.session, server_id, password) + def metadata(self, server_id): """This API lists metadata for a specified server. diff --git a/ecl/baremetal/v2/server.py b/ecl/baremetal/v2/server.py index d5f07cc..a0b38e1 100755 --- a/ecl/baremetal/v2/server.py +++ b/ecl/baremetal/v2/server.py @@ -269,6 +269,21 @@ def reset_bmc(self, session, server_id, type): self._translate_response(resp, has_body=False) return self + def update_bmc_password(self, session, server_id, password): + uri = self.base_path % server_id + body = { + "update-bmc-password": { + "password": password + } + } + resp = session.post( + uri, + endpoint_filter=self.service, + json=body + ) + self._translate_response(resp, has_body=False) + return self + @classmethod def find(cls, session, name_or_id, ignore_missing=False, **params): """Find a resource by its name or id. diff --git a/ecl/tests/functional/baremetal/test_server_action.py b/ecl/tests/functional/baremetal/test_server_action.py index cf58043..7ed80dd 100755 --- a/ecl/tests/functional/baremetal/test_server_action.py +++ b/ecl/tests/functional/baremetal/test_server_action.py @@ -19,30 +19,33 @@ class TestServerAction(base.BaseFunctionalTest): def test_01_start_server(self): server = self.conn.baremetal.start_server( - "752aac2e-4b82-4d47-a7c7-fcbd0cbc86e2", - "DISK" + "91f4e431-ab9d-422e-8f4f-9dcad809d18e" ) def test_02_stop_server(self): server = self.conn.baremetal.stop_server( - "752aac2e-4b82-4d47-a7c7-fcbd0cbc86e2", + "91f4e431-ab9d-422e-8f4f-9dcad809d18e", None ) - assert False + assert True def test_03_reboot_server(self): server = self.conn.baremetal.reboot_server( - "752aac2e-4b82-4d47-a7c7-fcbd0cbc86e2", - "SOFT", - "disk" + "91f4e431-ab9d-422e-8f4f-9dcad809d18e", + "SOFT" ) def test_04_get_management_console(self): server = self.conn.baremetal.get_management_console( - "752aac2e-4b82-4d47-a7c7-fcbd0cbc86e2", - None + "91f4e431-ab9d-422e-8f4f-9dcad809d18e" ) self.assertIsInstance(server.type, six.string_types) self.assertIsInstance(server.url, six.string_types) self.assertIsInstance(server.user_id, six.string_types) self.assertIsInstance(server.password, six.string_types) + + def test_07_update_bmc_password(self): + server = self.conn.baremetal.update_bmc_password( + "91f4e431-ab9d-422e-8f4f-9dcad809d18e", + "password20260210" + ) From e91d2fb51d4f17a98effadb165baa98e65a23879 Mon Sep 17 00:00:00 2001 From: t-yokoix Date: Thu, 12 Mar 2026 13:47:46 +0900 Subject: [PATCH 16/19] =?UTF-8?q?=E2=9C=A8Support=20Baremetal=20New=20RCA?= =?UTF-8?q?=20IF-16036=20(#218)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨Support Baremetal New RCA IF-16036 (#208) --- ecl/baremetal/v2/_proxy.py | 36 +++++++++++++++++++ ecl/baremetal/v2/server.py | 32 +++++++++++++++++ .../baremetal/test_server_action.py | 13 +++++++ 3 files changed, 81 insertions(+) diff --git a/ecl/baremetal/v2/_proxy.py b/ecl/baremetal/v2/_proxy.py index 33ff91d..8a5aa74 100755 --- a/ecl/baremetal/v2/_proxy.py +++ b/ecl/baremetal/v2/_proxy.py @@ -467,6 +467,42 @@ def reset_bmc(self, server_id, type): server = _server.ServerAction() return server.reset_bmc(self.session, server_id, type) + def get_remote_console_access(self, server_id): + """This API provides the necessary information to access the Bare Metal Server's + Baseboard Management Controller (BMC). + Specifically, it provides the destination URL and the access_code + required for access. + By appending /remote-console-token-exchange to the issued + URL, and sending a POST request with the access_code + specified in the request body in JSON format ({ "access_code": "" }), the access_token + will be returned in the Set-Cookie field of the response header. + You can then access the Bare Metal Server's BMC by accessing the issuedURL + with this access_token specified in the Cookie. + Please note that the validity period for the access_code is 1 minute, and the validity + period for the access_token is 1 hour. Once the access_token is retrieved + from an access_code, that access_code becomes invalid. + + :param string server_id: ID for the server. + :return: :class:`~ecl.baremetal.v2.server.ServerAction` + """ + server = _server.ServerAction() + return server.get_remote_console_access(self.session, server_id) + + def disconnect_remote_console_access(self, server_id): + """This API immediately revokes the access_token that was + issued by the aforementioned Get Remote Console Access + API, effectively expiring it prematurely. + Once the access_token is revoked, access to the BMC + using that access_token will no longer be possible, and + it will also become impossible to retrieve a access_token + using the access_code. + + :param string server_id: ID for the server. + :return: ``None`` + """ + server = _server.ServerAction() + return server.disconnect_remote_console_access(self.session, server_id) + def update_bmc_password(self, server_id, password): """Update the password for the Baseboard Management Controller of the Baremetal Server associated with server_id. diff --git a/ecl/baremetal/v2/server.py b/ecl/baremetal/v2/server.py index a0b38e1..f604527 100755 --- a/ecl/baremetal/v2/server.py +++ b/ecl/baremetal/v2/server.py @@ -153,6 +153,10 @@ class ServerAction(resource2.Resource): user_id = resource2.Body('user_id') #: Password for sign in to the remote console. password = resource2.Body('password') + #: Security token to get access_token. + access_code = resource2.Body('access_code') + #: Date and time when the access_code expires. + expired_at = resource2.Body('expired_at') def start(self, session, server_id): uri = self.base_path % server_id @@ -269,6 +273,34 @@ def reset_bmc(self, session, server_id, type): self._translate_response(resp, has_body=False) return self + def get_remote_console_access(self, session, server_id): + self.resource_key = "remote_console" + uri = self.base_path % server_id + body = { + "get-remote-console-url": None + } + resp = session.post( + uri, + endpoint_filter=self.service, + json=body, + headers={"Accept": "application/json"} + ) + self._translate_response(resp, has_body=True) + return self + + def disconnect_remote_console_access(self, session, server_id): + uri = self.base_path % server_id + body = { + "disconnect-remote-console": None + } + resp = session.post( + uri, + endpoint_filter=self.service, + json=body + ) + self._translate_response(resp, has_body=False) + return self + def update_bmc_password(self, session, server_id, password): uri = self.base_path % server_id body = { diff --git a/ecl/tests/functional/baremetal/test_server_action.py b/ecl/tests/functional/baremetal/test_server_action.py index 7ed80dd..ca7a933 100755 --- a/ecl/tests/functional/baremetal/test_server_action.py +++ b/ecl/tests/functional/baremetal/test_server_action.py @@ -44,6 +44,19 @@ def test_04_get_management_console(self): self.assertIsInstance(server.user_id, six.string_types) self.assertIsInstance(server.password, six.string_types) + def test_05_get_remote_console_access(self): + server = self.conn.baremetal.get_remote_console_access( + "91f4e431-ab9d-422e-8f4f-9dcad809d18e", + ) + self.assertIsInstance(server.url, six.string_types) + self.assertIsInstance(server.access_code, six.string_types) + self.assertIsInstance(server.expired_at, six.string_types) + + def test_06_disconnect_remote_console_access(self): + server = self.conn.baremetal.disconnect_remote_console_access( + "91f4e431-ab9d-422e-8f4f-9dcad809d18e", + ) + def test_07_update_bmc_password(self): server = self.conn.baremetal.update_bmc_password( "91f4e431-ab9d-422e-8f4f-9dcad809d18e", From 160856802d566ee26ac7f1055e9de654e3edf2aa Mon Sep 17 00:00:00 2001 From: MikuInoueTx Date: Mon, 30 Mar 2026 09:31:14 +0900 Subject: [PATCH 17/19] :sparkles:Support mVNA Day5 IF-17231 (#220) (#222) --- ecl/mvna/v1/system_update.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ecl/mvna/v1/system_update.py b/ecl/mvna/v1/system_update.py index 020f058..c142105 100644 --- a/ecl/mvna/v1/system_update.py +++ b/ecl/mvna/v1/system_update.py @@ -18,6 +18,7 @@ class SystemUpdate(resource2.Resource): "current_revision", "next_revision", "applicable", + "is_rollback_allowed", "latest" ) @@ -48,3 +49,5 @@ class SystemUpdate(resource2.Resource): next_revision = resource2.Body('next_revision') #: Applicable of system update applicable = resource2.Body('applicable') + #: Whether the system update can be rolled back + is_rollback_allowed = resource2.Body('is_rollback_allowed') From 58f6e77d6744118751191bd7bb7e5d83e2f0b3e3 Mon Sep 17 00:00:00 2001 From: sugimo-s <91592177+sugimo-s@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:47:19 +0900 Subject: [PATCH 18/19] Revert "Revert ":sparkles: Closing MSS v2 IF-16030 (#200)" (#211)" (#223) This reverts commit c1a1d6a5e7722c901e2e4c1766e5c7408bb322c7. --- ecl/profile.py | 2 +- ecl/security_order_v2/__init__.py | 0 .../security_order_service.py | 14 - ecl/security_order_v2/v2/__init__.py | 0 ecl/security_order_v2/v2/_proxy.py | 444 ------------------ ecl/security_order_v2/v2/device.py | 114 ----- ecl/security_order_v2/v2/ha_device.py | 110 ----- .../v2/host_based_security.py | 97 ---- ecl/security_order_v2/v2/waf.py | 115 ----- ecl/security_portal_v2/__init__.py | 0 .../security_portal_service.py | 14 - ecl/security_portal_v2/v2/__init__.py | 0 ecl/security_portal_v2/v2/_proxy.py | 49 -- ecl/security_portal_v2/v2/security_device.py | 47 -- .../v2/security_device_interface.py | 49 -- 15 files changed, 1 insertion(+), 1054 deletions(-) delete mode 100755 ecl/security_order_v2/__init__.py delete mode 100755 ecl/security_order_v2/security_order_service.py delete mode 100755 ecl/security_order_v2/v2/__init__.py delete mode 100755 ecl/security_order_v2/v2/_proxy.py delete mode 100644 ecl/security_order_v2/v2/device.py delete mode 100644 ecl/security_order_v2/v2/ha_device.py delete mode 100644 ecl/security_order_v2/v2/host_based_security.py delete mode 100644 ecl/security_order_v2/v2/waf.py delete mode 100755 ecl/security_portal_v2/__init__.py delete mode 100755 ecl/security_portal_v2/security_portal_service.py delete mode 100755 ecl/security_portal_v2/v2/__init__.py delete mode 100755 ecl/security_portal_v2/v2/_proxy.py delete mode 100644 ecl/security_portal_v2/v2/security_device.py delete mode 100644 ecl/security_portal_v2/v2/security_device_interface.py diff --git a/ecl/profile.py b/ecl/profile.py index 23a510a..02afdf6 100755 --- a/ecl/profile.py +++ b/ecl/profile.py @@ -110,7 +110,7 @@ def __init__(self, plugins=None): self._add_service( security_order_service.SecurityOrderService(version="v3")) self._add_service( - security_portal_service.SecurityPortalService(version="v2")) + security_portal_service.SecurityPortalService(version="v3")) self._add_service(rca_service.RcaService(version="v1")) self._add_service(baremetal_service.BaremetalService(version="v2")) self._add_service( diff --git a/ecl/security_order_v2/__init__.py b/ecl/security_order_v2/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_order_v2/security_order_service.py b/ecl/security_order_v2/security_order_service.py deleted file mode 100755 index 5e28aea..0000000 --- a/ecl/security_order_v2/security_order_service.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl import service_filter - - -class SecurityOrderService(service_filter.ServiceFilter): - """The security service.""" - - valid_versions = [service_filter.ValidVersion('v2')] - - def __init__(self, version=None): - """Create a security service.""" - super(SecurityOrderService, self).__init__(service_type='security-order', - version=version) diff --git a/ecl/security_order_v2/v2/__init__.py b/ecl/security_order_v2/v2/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_order_v2/v2/_proxy.py b/ecl/security_order_v2/v2/_proxy.py deleted file mode 100755 index a4cd2d6..0000000 --- a/ecl/security_order_v2/v2/_proxy.py +++ /dev/null @@ -1,444 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v2.v2 import device as _fgs -from ecl.security_order_v2.v2 import ha_device as _fgha -from ecl.security_order_v2.v2 import waf as _fgwaf -from ecl.security_order_v2.v2 import host_based_security as _hbs -from ecl import proxy2 - - -class Proxy(proxy2.BaseProxy): - - def devices(self, locale=None): - """List Managed Firwall/UTM devices of single constitution. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v2.device.Device` - """ - fgs = _fgs.Device() - return fgs.list(self.session, locale=locale) - - def create_device(self, operatingmode, licensekind, - azgroup, locale=None): - """Create a new Managed Firewall/UTM device of single constitution. - - :param string operatingmode: Set "FW" or "UTM" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string azgroup: Availability Zone - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v2.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup - }] - body["sokind"] = "A" - if locale: - body["locale"] = locale - return self._create(_fgs.Device, **body) - - def update_device(self, hostname, operatingmode, - licensekind, locale=None): - """Change menu (Firewall/Managed UTM) and/or plan of single device. - - :param string operatingmode: Set "FW" or "UTM" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v2.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname, - "operatingmode": operatingmode, - "licensekind": licensekind - }] - body["sokind"] = "M" - if locale: - body.update({"locale": locale}) - fgs = _fgs.Device() - return fgs.update(self.session, **body) - - def delete_device(self, hostname, locale=None): - """Delete a Managed Firewall/UTM device of single constitution. - - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v2.device.Device` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname - }] - body["sokind"] = "D" - if locale: - body["locale"] = locale - fgs = _fgs.Device() - return fgs.delete(self.session, body, locale=locale) - - def ha_devices(self, locale=None): - """List Managed Firwall/UTM devices of single constitution. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v2.ha_device.HADevice` - """ - fgha = _fgha.HADevice() - return fgha.list(self.session, locale=locale) - - def create_ha_device(self, operatingmode, licensekind, - azgroup1, azgroup2, - halink1networkid, halink1subnetid, - halink1ipaddress1, halink1ipaddress2, - halink2networkid, halink2subnetid, - halink2ipaddress1, halink2ipaddress2, - locale=None): - """Create a new Managed Firewall/UTM device of single constitution. - - :param string operatingmode: Set "UTM_HA" or "FW_HA" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string azgroup1: Availability Zone - :param string azgroup2: Availability Zone - :param string halink1networkid: Set Network ID to be used for HA line. - :param string halink1subnetid: Set Subnet ID to be used for HA line. - :param string halink1ipaddress1: Set value of IPv4. - :param string halink1ipaddress2: Set value of IPv4. - :param string halink2networkid: Set Network ID to be used for HA line. - :param string halink2subnetid: Set Subnet ID to be used for HA line. - :param string halink2ipaddress1: Set value of IPv4. - :param string halink2ipaddress2: Set value of IPv4. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v2.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup1, - "halink1networkid": halink1networkid, - "halink1subnetid": halink1subnetid, - "halink1ipaddress": halink1ipaddress1, - "halink2networkid": halink2networkid, - "halink2subnetid": halink2subnetid, - "halink2ipaddress": halink2ipaddress1 - },{ - "operatingmode": operatingmode, - "licensekind": licensekind, - "azgroup": azgroup2, - "halink1networkid": halink1networkid, - "halink1subnetid": halink1subnetid, - "halink1ipaddress": halink1ipaddress2, - "halink2networkid": halink2networkid, - "halink2subnetid": halink2subnetid, - "halink2ipaddress": halink2ipaddress2 - }] - body["sokind"] = "AH" - if locale: - body["locale"] = locale - return self._create(_fgha.HADevice, **body) - - def update_ha_device(self, hostname1, hostname2, operatingmode, - licensekind, locale=None): - """Change menu (Firewall/Managed UTM) and/or plan of single device. - - :param string hostname1: Set the hostname. - :param string hostname2: Set the hostname. - :param string operatingmode: Set "UTM_HA" or "FW_HA" to this value. - :param string licensekind: Set "02" or "08" as FW/UTM plan. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v2.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname1, - "operatingmode": operatingmode, - "licensekind": licensekind - },{ - "hostname": hostname2, - "operatingmode": operatingmode, - "licensekind": licensekind - }] - body["sokind"] = "MH" - if locale: - body.update({"locale": locale}) - fgha = _fgha.HADevice() - return fgha.update(self.session, **body) - - def delete_ha_device(self, hostname1, hostname2, locale=None): - """Delete a Managed Firewall/UTM device of single constitution. - - :param string hostname1: Set the hostname. - :param string hostname2: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: HA Firwall/UTM. - :rtype: :class:`~ecl.security.v2.ha_device.HADevice` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname1 - }, { - "hostname": hostname2 - }] - body["sokind"] = "DH" - if locale: - body["locale"] = locale - fgha = _fgha.HADevice() - return fgha.delete(self.session, body, locale=locale) - - def get_device_order_status(self, soid, locale=None): - """Check progress status of Managed Firewall/UTM device Service Order. - - :param string soid: This value is returned value of when you execute - Create Server, Update Server or Delete Server API. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Single Firwall/UTM. - :rtype: :class:`~ecl.security.v2.device.Device` - """ - fgs = _fgs.Device() - return fgs.get_order_status(self.session, soid, locale=locale) - - def wafs(self, locale=None): - """List active waf devices you ordered. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v2.waf.WAF` - """ - fgwaf = _fgwaf.WAF() - return fgwaf.list(self.session, locale=locale) - - def create_waf(self, licensekind, azgroup, locale=None): - """Create a new WAF device. - - :param string licensekind: Set "02", "04" or "08" as WAF plan. - :param string azgroup: Availability Zone - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v2.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "operatingmode": "WAF", - "licensekind": licensekind, - "azgroup": azgroup - }] - body["sokind"] = "A" - if locale: - body["locale"] = locale - return self._create(_fgwaf.WAF, **body) - - def get_waf_order_status(self, soid, locale=None): - """Check progress status of Managed WAF device Service Order. - - :param string soid: This value is returned value of when you execute - Create Server, Update Server or Delete Server API. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v2.waf.WAF` - """ - fgwaf = _fgwaf.WAF() - return fgwaf.get_order_status(self.session, soid, locale=locale) - - def update_waf(self, hostname, licensekind, locale=None): - """Change plan of device. - - :param string licensekind: Set "02", "04" or "08" as WAF plan. - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v2.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname, - "licensekind": licensekind - }] - body["sokind"] = "M" - if locale: - body.update({"locale": locale}) - fgwaf = _fgwaf.WAF() - return fgwaf.update(self.session, **body) - - def delete_waf(self, hostname, locale=None): - """Delete a WAF device. - - :param string hostname: Set the hostname. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: WAF. - :rtype: :class:`~ecl.security.v2.waf.WAF` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["gt_host"] = [{ - "hostname": hostname - }] - body["sokind"] = "D" - if locale: - body["locale"] = locale - fgwaf = _fgwaf.WAF() - return fgwaf.delete(self.session, body, locale=locale) - - def get_hbs_order_status(self, soid, locale=None): - """Check progress status of Host-based Security Service Order. - - :param string soid: This value is returned value of when you execute API - of Order Host-based Security, Change menu or - quantity, or Cancel the order. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - hbs = _hbs.HostBasedSecurity() - return hbs.get_order_status(self.session, soid, locale=locale) - - def get_hbs_order_info(self, locale=None): - """Get Order Information that tied to tenant id. - - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - hbs = _hbs.HostBasedSecurity() - return hbs.get_order_info(self.session, locale=locale) - - def order_hbs(self, service_order_service, max_agent_value, - mailaddress, dsm_lang, time_zone, - locale=None): - """Make a new application for Host-based Security. - - :param string service_order_service: Requested menu. - Set "Managed Anti-Virus", "Managed Virtual Patch" - or "Managed Host-based Security Package" to this field. - :param string max_agent_value: Set maximum quantity of Agenet usage. - :param string mailaddress: Contactable mail address. - :param string dsm_lang: This value is used for language of Deep - Security Manager. ja: Japanese, en: English. - :param string time_zone: Set "Asia/Tokyo" for JST or "Etc/GMT" for UTC. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["service_order_service"] = service_order_service - body["max_agent_value"] = max_agent_value - body["mailaddress"] = mailaddress - body["dsm_lang"] = dsm_lang - body["time_zone"] = time_zone - body["sokind"] = "N" - if locale: - body["locale"] = locale - return self._create(_hbs.HostBasedSecurity, **body) - - def change_hbs_menu(self, service_order_service, mailaddress, locale=None): - """Change menu of Host-based Security. - - :param string service_order_service: Requested menu. - Set "Managed Anti-Virus", "Managed Virtual Patch" - or "Managed Host-based Security Package" to this field. - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["service_order_service"] = service_order_service - body["mailaddress"] = mailaddress - body["sokind"] = "M1" - if locale: - body.update({"locale": locale}) - hbs = _hbs.HostBasedSecurity() - return hbs.update(self.session, **body) - - def change_hbs_quantity(self, max_agent_value, mailaddress, locale=None): - """Change maximum quantity of Agent usage. - - :param string max_agent_value: Set maximum quantity of Agenet usage. - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["max_agent_value"] = max_agent_value - body["mailaddress"] = mailaddress - body["sokind"] = "M2" - if locale: - body.update({"locale": locale}) - hbs = _hbs.HostBasedSecurity() - return hbs.update(self.session, **body) - - def cancel_hbs(self, mailaddress, locale=None): - """Cancel the order of Host-based Security. - - :param string mailaddress: Contactable mail address. - :param string locale: Messages are displayed in Japanese or English - depending on this value. - ja: Japanese, en: English. Default value is "en". - :return: Host Based Security. - :rtype: :class:`~ecl.security.v2.host_based_security.HostBasedSecurity` - """ - body = {} - body["tenant_id"] = self.session.get_project_id() - body["mailaddress"] = mailaddress - body["sokind"] = "C" - if locale: - body["locale"] = locale - hbs = _hbs.HostBasedSecurity() - return hbs.delete(self.session, body, locale=locale) diff --git a/ecl/security_order_v2/v2/device.py b/ecl/security_order_v2/v2/device.py deleted file mode 100644 index 784d0f8..0000000 --- a/ecl/security_order_v2/v2/device.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v2 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class Device(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGS' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "FW" or "UTM" to this value. - #: licensekind: Set "02" or "08" as FW/UTM plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGSOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGSDeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'hostname': row['cell'][2], - 'menu': row['cell'][3], - 'plan': row['cell'][4], - 'redundancy': row['cell'][5], - 'availability_zone': row['cell'][6], - 'zone_name': row['cell'][7], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_order_v2/v2/ha_device.py b/ecl/security_order_v2/v2/ha_device.py deleted file mode 100644 index 5711ce9..0000000 --- a/ecl/security_order_v2/v2/ha_device.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v2 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class HADevice(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGHA' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "FW" or "UTM" to this value. - #: licensekind: Set "02" or "08" as FW/UTM plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGHADeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'ha_id': row['cell'][2], - 'hostname': row['cell'][3], - 'menu': row['cell'][4], - 'plan': row['cell'][5], - 'redundancy': row['cell'][6], - 'availability_zone': row['cell'][7], - 'zone_name': row['cell'][8], - 'halink1networkid': row['cell'][9], - 'halink1subnetid': row['cell'][10], - 'halink1ipaddress': row['cell'][11], - 'halink2networkid': row['cell'][12], - 'halink2subnetid': row['cell'][13], - 'halink2ipaddress': row['cell'][14], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_order_v2/v2/host_based_security.py b/ecl/security_order_v2/v2/host_based_security.py deleted file mode 100644 index 65ceeee..0000000 --- a/ecl/security_order_v2/v2/host_based_security.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v2 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - -class HostBasedSecurity(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryHBS' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: N: Order New Host-based Security. - #: M1: Change menu of Host-based Security. - #: M2: Change quantity of Host-based Security. - #: C: Cancel Host-based Security. - sokind = resource2.Body('sokind') - #: Requested menu. Set "Managed Anti-Virus", "Managed Virtual Patch" - #: or "Managed Host-based Security Package" to this field. - service_order_service = resource2.Body('service_order_service') - #: Set maximum quantity of Agenet usage. - max_agent_value = resource2.Body('max_agent_value') - #: Contactable mail address. - mailaddress = resource2.Body('mailaddress') - #: This value is used for language of Deep Security Manager. - #: ja: Japanese, en: English. - dsm_lang = resource2.Body('dsm_lang') - #: Set "Asia/Tokyo" for JST or "Etc/GMT" for UTC. - time_zone = resource2.Body('time_zone') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - #: Region tenant you specified belongs to. - region = resource2.Body('region') - #: Tenant Name. - tenant_name = resource2.Body('tenant_name') - #: Description for this tenant. - tenant_description = resource2.Body('tenant_description') - #: Contract ID which this tenant belongs to. - contract_id = resource2.Body('contract_id') - #: Customer Name. - customer_name = resource2.Body('customer_name') - #: Internal Use. (true: Already applied, false: Not applied.) - tenant_flg = resource2.Body('tenant_flg') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventHBSOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def get_order_info(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventHBSOrderInfoGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self diff --git a/ecl/security_order_v2/v2/waf.py b/ecl/security_order_v2/v2/waf.py deleted file mode 100644 index 8d02b8e..0000000 --- a/ecl/security_order_v2/v2/waf.py +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_order_v2 import security_order_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class WAF(resource2.Resource): - resource_key = None - resources_key = None - base_path = '/API/SoEntryFGWAF' - service = security_order_service.SecurityOrderService() - - # Capabilities - allow_create = True - allow_get = True - allow_delete = True - allow_list = True - allow_update = True - - # Properties - #: Tenant ID of the owner (UUID). - tenant_id = resource2.Body('tenant_id') - #: List of following objects. - #: operatingmode: Set "WAF" to this value. - #: licensekind: Set "02", "04" or "08" as WAF plan. - #: azgroup: Availability Zone. - gt_host = resource2.Body('gt_host') - #: A: Create Single Constitution Device. - #: M: Update Single Constitution Device. - #: D: Delete Single Constitution Device. - sokind = resource2.Body('sokind') - #: Messages are displayed in Japanese or English depending on this value. - #: ja: Japanese, en: English. Default value is "en". - locale = resource2.Body('locale') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - code = resource2.Body('code', alternate_id=True) - #: This message is shown when error has occurred. - message = resource2.Body('message') - #: Identification ID of Service Order. - soid = resource2.Body('soId') - #: This value indicates normal or abnormal. 1:normal, 2:abnormal. - status = resource2.Body('status') - #: Number of devices. - records = resource2.Body('records') - #: Device list. - rows = resource2.Body('rows') - #: List of device objects. - devices = resource2.Body('devices') - #: Percentage of Service Order Progress Status. - progress_rate = resource2.Body('progressRate') - #: List of device objects. - devices = resource2.Body('devices') - - def get_order_status(self, session, soid, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGWAFOrderProgressRate?tenant_id=%s&soid=%s' \ - % (tenant_id, soid) - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - self._translate_response(resp, has_body=True) - return self - - def update(self, session, **body): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def delete(self, session, body, locale=None): - uri = self.base_path - resp = session.post(uri, endpoint_filter=self.service, json=body) - self._translate_response(resp, has_body=True) - return self - - def list(self, session, locale=None): - tenant_id = session.get_project_id() - uri = '/API/ScreenEventFGWAFDeviceGet?tenant_id=%s' % tenant_id - if locale is not None: - uri += '&locale=%s' % locale - headers = {'Content-Type': 'application/json'} - resp = session.get(uri, endpoint_filter=self.service, headers=headers) - body = resp.json() - devices = [] - for row in body['rows']: - device = { - 'internal_use': row['cell'][0], - 'rows': row['cell'][1], - 'hostname': row['cell'][2], - 'menu': row['cell'][3], - 'plan': row['cell'][4], - 'availability_zone': row['cell'][5], - 'zone_name': row['cell'][6], - } - devices.append(device) - body.update({'devices': devices}) - self._translate_list_response(resp, body, has_body=True) - return self - - def _translate_list_response(self, response, body, has_body=True): - if has_body: - if self.resource_key and self.resource_key in body: - body = body[self.resource_key] - - body = self._filter_component(body, self._body_mapping()) - self._body.attributes.update(body) - self._body.clean() - - headers = self._filter_component(response.headers, - self._header_mapping()) - self._header.attributes.update(headers) - self._header.clean() diff --git a/ecl/security_portal_v2/__init__.py b/ecl/security_portal_v2/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_portal_v2/security_portal_service.py b/ecl/security_portal_v2/security_portal_service.py deleted file mode 100755 index 43bfd3c..0000000 --- a/ecl/security_portal_v2/security_portal_service.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl import service_filter - - -class SecurityPortalService(service_filter.ServiceFilter): - """The security service.""" - - valid_versions = [service_filter.ValidVersion('v2')] - - def __init__(self, version=None): - """Create a security service.""" - super(SecurityPortalService, self).__init__(service_type='security-operation', - version=version) diff --git a/ecl/security_portal_v2/v2/__init__.py b/ecl/security_portal_v2/v2/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/ecl/security_portal_v2/v2/_proxy.py b/ecl/security_portal_v2/v2/_proxy.py deleted file mode 100755 index f5919ef..0000000 --- a/ecl/security_portal_v2/v2/_proxy.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v2.v2 import security_device as _sd -from ecl.security_portal_v2.v2 import security_device_interface as _sdi -from ecl import proxy2 - - -class Proxy(proxy2.BaseProxy): - def security_devices(self): - """Listing security devices associated with specific tenant. - - :return: List security devices. - :rtype: :class:`~ecl.security_portal.v2.security_device.SecurityDevice` - """ - return list(self._list(_sd.SecurityDevice, paginated=False, - tenantid=self.session.get_project_id(), - usertoken=self.session.get_token())) - - def get_security_device(self, server_id): - """Show security device details associated with specific tenant. - - :param string server_id: Server ID registered in Openstack(UUID). - :return: One security device. - :rtype: :class:`~ecl.security_portal.v2.security_device.SecurityDevice` - """ - sd = _sd.SecurityDevice() - return sd.get(self.session, server_id) - - def security_device_interfaces(self, server_id): - """Listing security device Interfaces associated with specific tenant. - - :param string server_id: Server ID registered in Openstack(UUID). - :return: List security device interfaces. - :rtype: :class:`~ecl.security_portal.v2.security_device_interface.SecurityDeviceInterface` - """ - return list(self._list(_sdi.SecurityDeviceInterface, paginated=False, - server_id=server_id, - tenantid=self.session.get_project_id(), - usertoken=self.session.get_token())) - - def get_security_device_interface(self, port_id): - """Show security device Interface associated with specific tenant. - - :param string port_id: Port ID registered in Openstack(UUID). - :return: One security device interface. - :rtype: :class:`~ecl.security_portal.v2.security_device_interface.SecurityDeviceInterface` - """ - sdi = _sdi.SecurityDeviceInterface() - return sdi.get(self.session, port_id) diff --git a/ecl/security_portal_v2/v2/security_device.py b/ecl/security_portal_v2/v2/security_device.py deleted file mode 100644 index 9631c35..0000000 --- a/ecl/security_portal_v2/v2/security_device.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v2 import security_portal_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class SecurityDevice(resource2.Resource): - resource_key = "device" - resources_key = "devices" - base_path = '/ecl-api/devices' - service = security_portal_service.SecurityPortalService() - - _query_mapping = resource2.QueryParameters( - "tenantid", - "usertoken", - ) - - # Capabilities - allow_get = True - allow_list = True - - # Properties - #: MSA Device External reference. - msa_device_id = resource2.Body('msa_device_id', alternate_id=True) - #: MSA Device Type. - msa_device_type = resource2.Body('msa_device_type') - #: Server id of Network-based Security devices. - os_server_id = resource2.Body('os_server_id') - #: Server name on Openstack. - os_server_name = resource2.Body('os_server_name') - #: Availability zone information. - os_availability_zone = resource2.Body('os_availability_zone') - #: Name of admin. - os_admin_username = resource2.Body('os_admin_username') - #: Server Status. - os_server_status = resource2.Body('os_server_status') - #: Interfaces details associated with the Security Device. - interfaces = resource2.Body('interfaces') - - def get(self, session, server_id): - uri = self.base_path + '/%s?tenantid=%s&usertoken=%s' \ - % (server_id, session.get_project_id(), session.get_token()) - resp = session.get(uri, endpoint_filter=self.service) - self._translate_response(resp, has_body=True) - return self diff --git a/ecl/security_portal_v2/v2/security_device_interface.py b/ecl/security_portal_v2/v2/security_device_interface.py deleted file mode 100644 index 7884114..0000000 --- a/ecl/security_portal_v2/v2/security_device_interface.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -from ecl.security_portal_v2 import security_portal_service -from ecl import resource2 -from ecl import exceptions -from ecl import utils - - -class SecurityDeviceInterface(resource2.Resource): - resource_key = "device_interface" - resources_key = "device_interfaces" - base_path = '/ecl-api/devices/%(server_id)s/interfaces' - service = security_portal_service.SecurityPortalService() - - _query_mapping = resource2.QueryParameters( - "tenantid", - "usertoken", - ) - - # Capabilities - allow_get = True - allow_list = True - - # Properties - #: Port id on Openstack. - os_port_id = resource2.Body('os_port_id', alternate_id=True) - #: Port IP address (if available). - os_ip_address = resource2.Body('os_ip_address') - #: Port id on the Network-based Security devices (registered in MSA). - msa_port_id = resource2.Body('msa_port_id') - #: Port name on Openstack. - os_port_name = resource2.Body('os_port_name') - #: Network Id to which Port is associated on Openstack. - os_network_id = resource2.Body('os_network_id') - #: Port Status on Openstack. - os_port_status = resource2.Body('os_port_status') - #: Port MAC address on Openstack. - os_mac_address = resource2.Body('os_mac_address') - #: Subnet Id to which Port is associated on Openstack. - os_subnet_id = resource2.Body('os_subnet_id') - #: Server id of Network-based Security devices. - os_server_id = resource2.Body('os_server_id') - - def get(self, session, port_id): - uri = '/ecl-api/devices/interface/%s?tenantid=%s&usertoken=%s' \ - % (port_id, session.get_project_id(), session.get_token()) - resp = session.get(uri, endpoint_filter=self.service) - self._translate_response(resp, has_body=True) - return self From 730da6134d4585b15a31452185c31f083ca60584 Mon Sep 17 00:00:00 2001 From: "sugimoto.shigeki" Date: Fri, 14 Aug 2026 13:44:23 +0900 Subject: [PATCH 19/19] :bookmark: IF-18437 Version Up --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index c8944d7..db38bbe 100755 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = eclsdk -version = 1.9.0 +version = 1.10.0 summary = SDK for building applications to work with Enterprise Cloud 2.0 description-file = README.rst