github.com/yasker/longhorn-engine@v0.0.0-20160621014712-6ed6cfca0729/integration/core/test_cli.py (about)

     1  import time
     2  import random
     3  from os import path
     4  import os
     5  import subprocess
     6  import json
     7  
     8  import pytest
     9  import cattle
    10  
    11  
    12  REPLICA = 'tcp://localhost:9502'
    13  REPLICA2 = 'tcp://localhost:9505'
    14  
    15  BACKUP_DEST = '/tmp/longhorn-backup'
    16  
    17  VOLUME_NAME = 'test-volume'
    18  VOLUME_SIZE = str(4 * 1024 * 1024)  # 4M
    19  
    20  
    21  @pytest.fixture
    22  def controller_client(request):
    23      url = 'http://localhost:9501/v1/schemas'
    24      c = cattle.from_env(url=url)
    25      request.addfinalizer(lambda: cleanup_controller(c))
    26      c = cleanup_controller(c)
    27      assert c.list_volume()[0].replicaCount == 0
    28      return c
    29  
    30  
    31  def cleanup_controller(client):
    32      for r in client.list_replica():
    33          client.delete(r)
    34      return client
    35  
    36  
    37  @pytest.fixture
    38  def replica_client(request):
    39      url = 'http://localhost:9502/v1/schemas'
    40      c = cattle.from_env(url=url)
    41      request.addfinalizer(lambda: cleanup_replica(c))
    42      return cleanup_replica(c)
    43  
    44  
    45  @pytest.fixture
    46  def replica_client2(request):
    47      url = 'http://localhost:9505/v1/schemas'
    48      c = cattle.from_env(url=url)
    49      request.addfinalizer(lambda: cleanup_replica(c))
    50      return cleanup_replica(c)
    51  
    52  
    53  def cleanup_replica(client):
    54      r = client.list_replica()[0]
    55      if r.state == 'initial':
    56          return client
    57      if 'open' in r:
    58          r = r.open()
    59      client.delete(r)
    60      r = client.reload(r)
    61      assert r.state == 'initial'
    62      return client
    63  
    64  
    65  @pytest.fixture
    66  def random_str():
    67      return 'random-{0}-{1}'.format(random_num(), int(time.time()))
    68  
    69  
    70  def random_num():
    71      return random.randint(0, 1000000)
    72  
    73  
    74  def _file(f):
    75      return path.join(_base(), '../../{}'.format(f))
    76  
    77  
    78  def _base():
    79      return path.dirname(__file__)
    80  
    81  
    82  @pytest.fixture(scope='session')
    83  def bin():
    84      c = _file('bin/longhorn')
    85      assert path.exists(c)
    86      return c
    87  
    88  
    89  def setup_module():
    90      if os.path.exists(BACKUP_DEST):
    91          subprocess.check_call(["rm", "-rf", BACKUP_DEST])
    92  
    93      os.makedirs(BACKUP_DEST)
    94      assert os.path.exists(BACKUP_DEST)
    95  
    96  
    97  def open_replica(client):
    98      replicas = client.list_replica()
    99      assert len(replicas) == 1
   100  
   101      r = replicas[0]
   102      assert r.state == 'initial'
   103      assert r.size == '0'
   104      assert r.sectorSize == 0
   105      assert r.parent == ''
   106      assert r.head == ''
   107  
   108      r = r.create(size=str(1024 * 4096))
   109  
   110      assert r.state == 'closed'
   111      assert r.size == str(1024 * 4096)
   112      assert r.sectorSize == 512
   113      assert r.parent == ''
   114      assert r.head == 'volume-head-000.img'
   115  
   116      return r
   117  
   118  
   119  def test_replica_add_start(bin, controller_client, replica_client):
   120      open_replica(replica_client)
   121  
   122      cmd = [bin, '--debug', 'add-replica', REPLICA]
   123      subprocess.check_call(cmd)
   124  
   125      volume = controller_client.list_volume()[0]
   126      assert volume.replicaCount == 1
   127  
   128  
   129  def test_replica_add_rebuild(bin, controller_client, replica_client,
   130                               replica_client2):
   131      open_replica(replica_client)
   132      open_replica(replica_client2)
   133  
   134      r = replica_client.list_replica()[0]
   135      r = r.open()
   136      r = r.snapshot(name='000')
   137      r = r.snapshot(name='001')
   138  
   139      l = replica_client2.list_replica()[0]
   140  
   141      assert r.chain == ['volume-head-002.img',
   142                         'volume-snap-001.img',
   143                         'volume-snap-000.img']
   144  
   145      assert l.chain != ['volume-head-002.img',
   146                         'volume-snap-001.img',
   147                         'volume-snap-000.img']
   148  
   149      r = r.close()
   150      cmd = [bin, '--debug', 'add-replica', REPLICA]
   151      subprocess.check_call(cmd)
   152  
   153      volume = controller_client.list_volume()[0]
   154      assert volume.replicaCount == 1
   155  
   156      cmd = [bin, '--debug', 'add-replica', REPLICA2]
   157      subprocess.check_call(cmd)
   158  
   159      volume = controller_client.list_volume()[0]
   160      assert volume.replicaCount == 2
   161  
   162      replicas = controller_client.list_replica()
   163      assert len(replicas) == 2
   164  
   165      for r in replicas:
   166          assert r.mode == 'RW'
   167  
   168  
   169  def test_replica_add_after_rebuild_failed(bin, controller_client,
   170                                            replica_client, replica_client2):
   171      open_replica(replica_client)
   172      open_replica(replica_client2)
   173  
   174      r = replica_client.list_replica()[0]
   175      r = r.open()
   176      r = r.snapshot(name='000')
   177      r.close()
   178  
   179      cmd = [bin, '--debug', 'add-replica', REPLICA]
   180      subprocess.check_call(cmd)
   181  
   182      volume = controller_client.list_volume()[0]
   183      assert volume.replicaCount == 1
   184  
   185      l = replica_client2.list_replica()[0]
   186      l = l.open()
   187      l = l.setrebuilding(rebuilding=True)
   188      l.close()
   189  
   190      cmd = [bin, '--debug', 'add-replica', REPLICA2]
   191      subprocess.check_call(cmd)
   192  
   193      volume = controller_client.list_volume()[0]
   194      assert volume.replicaCount == 2
   195  
   196      replicas = controller_client.list_replica()
   197      assert len(replicas) == 2
   198  
   199      for r in replicas:
   200          assert r.mode == 'RW'
   201  
   202  
   203  def test_revert(bin, controller_client, replica_client, replica_client2):
   204      open_replica(replica_client)
   205      open_replica(replica_client2)
   206  
   207      v = controller_client.list_volume()[0]
   208      v = v.start(replicas=[
   209          REPLICA,
   210          REPLICA2,
   211      ])
   212      assert v.replicaCount == 2
   213  
   214      snap = v.snapshot(name='foo1')
   215      assert snap.id == 'foo1'
   216  
   217      snap2 = v.snapshot(name='foo2')
   218      assert snap2.id == 'foo2'
   219  
   220      r1 = replica_client.list_replica()[0]
   221      r2 = replica_client2.list_replica()[0]
   222  
   223      assert r1.chain == ['volume-head-002.img', 'volume-snap-foo2.img',
   224                          'volume-snap-foo1.img']
   225      assert r1.chain == r2.chain
   226  
   227      v.revert(name='foo1')
   228  
   229      r1 = replica_client.list_replica()[0]
   230      r2 = replica_client2.list_replica()[0]
   231      assert r1.chain == ['volume-head-003.img', 'volume-snap-foo1.img']
   232      assert r1.chain == r2.chain
   233  
   234  
   235  def test_snapshot(bin, controller_client, replica_client, replica_client2):
   236      open_replica(replica_client)
   237      open_replica(replica_client2)
   238  
   239      v = controller_client.list_volume()[0]
   240      v = v.start(replicas=[
   241          REPLICA,
   242          REPLICA2,
   243      ])
   244      assert v.replicaCount == 2
   245  
   246      snap = v.snapshot(name='foo1')
   247      assert snap.id == 'foo1'
   248  
   249      snap2 = v.snapshot(name='foo2')
   250      assert snap2.id == 'foo2'
   251  
   252      cmd = [bin, '--debug', 'snapshot']
   253      output = subprocess.check_output(cmd)
   254  
   255      assert output == '''ID
   256  {}
   257  {}
   258  '''.format(snap2.id, snap.id)
   259  
   260  
   261  def test_snapshot_ls(bin, controller_client, replica_client, replica_client2):
   262      open_replica(replica_client)
   263      open_replica(replica_client2)
   264  
   265      v = controller_client.list_volume()[0]
   266      v = v.start(replicas=[
   267          REPLICA,
   268          REPLICA2,
   269      ])
   270      assert v.replicaCount == 2
   271  
   272      snap = v.snapshot()
   273      assert snap.id != ''
   274  
   275      snap2 = v.snapshot()
   276      assert snap2.id != ''
   277  
   278      cmd = [bin, '--debug', 'snapshot', 'ls']
   279      output = subprocess.check_output(cmd)
   280  
   281      assert output == '''ID
   282  {}
   283  {}
   284  '''.format(snap2.id, snap.id)
   285  
   286  
   287  def test_snapshot_create(bin, controller_client, replica_client,
   288                           replica_client2):
   289      open_replica(replica_client)
   290      open_replica(replica_client2)
   291  
   292      v = controller_client.list_volume()[0]
   293      v = v.start(replicas=[
   294          REPLICA,
   295          REPLICA2,
   296      ])
   297      assert v.replicaCount == 2
   298  
   299      cmd = [bin, 'snapshot', 'create']
   300      output = subprocess.check_output(cmd).strip()
   301      expected = replica_client.list_replica()[0].chain[1]
   302  
   303      assert expected == 'volume-snap-{}.img'.format(output)
   304  
   305      cmd = [bin, '--debug', 'snapshot', 'ls']
   306      ls_output = subprocess.check_output(cmd)
   307  
   308      assert ls_output == '''ID
   309  {}
   310  '''.format(output)
   311  
   312  
   313  def test_snapshot_rm(bin, controller_client, replica_client, replica_client2):
   314      open_replica(replica_client)
   315      open_replica(replica_client2)
   316  
   317      v = controller_client.list_volume()[0]
   318      v = v.start(replicas=[
   319          REPLICA,
   320          REPLICA2,
   321      ])
   322      assert v.replicaCount == 2
   323  
   324      cmd = [bin, 'snapshot', 'create']
   325      subprocess.check_call(cmd)
   326      output = subprocess.check_output(cmd).strip()
   327  
   328      chain = replica_client.list_replica()[0].chain
   329      assert len(chain) == 3
   330      assert chain[0] == 'volume-head-002.img'
   331      assert chain[1] == 'volume-snap-{}.img'.format(output)
   332  
   333      cmd = [bin, 'snapshot', 'rm', output]
   334      subprocess.check_call(cmd)
   335  
   336      new_chain = replica_client.list_replica()[0].chain
   337      assert len(new_chain) == 2
   338      assert chain[0] == new_chain[0]
   339      assert chain[2] == new_chain[1]
   340  
   341  
   342  def test_snapshot_last(bin, controller_client, replica_client,
   343                         replica_client2):
   344      open_replica(replica_client)
   345      open_replica(replica_client2)
   346  
   347      v = controller_client.list_volume()[0]
   348      v = v.start(replicas=[
   349          REPLICA,
   350      ])
   351      assert v.replicaCount == 1
   352  
   353      cmd = [bin, 'add', REPLICA2]
   354      subprocess.check_output(cmd)
   355      output = subprocess.check_output([bin, 'snapshot', 'ls'])
   356      output = output.splitlines()[1]
   357  
   358      chain = replica_client.list_replica()[0].chain
   359      assert len(chain) == 2
   360      assert chain[0] == 'volume-head-001.img'
   361      assert chain[1] == 'volume-snap-{}.img'.format(output)
   362  
   363      chain = replica_client2.list_replica()[0].chain
   364      assert len(chain) == 2
   365      assert chain[0] == 'volume-head-001.img'
   366      assert chain[1] == 'volume-snap-{}.img'.format(output)
   367  
   368      # it will be marked as removed
   369      cmd = [bin, 'snapshot', 'rm', output]
   370      subprocess.check_call(cmd)
   371  
   372  
   373  def test_backup_core(bin, controller_client, replica_client,
   374                       replica_client2):
   375      open_replica(replica_client)
   376      open_replica(replica_client2)
   377  
   378      v = controller_client.list_volume()[0]
   379      v = v.start(replicas=[
   380          REPLICA,
   381          REPLICA2,
   382      ])
   383      assert v.replicaCount == 2
   384  
   385      cmd = [bin, 'snapshot', 'create']
   386      output = subprocess.check_output(cmd).strip()
   387      snapshot1 = replica_client.list_replica()[0].chain[1]
   388  
   389      assert snapshot1 == 'volume-snap-{}.img'.format(output)
   390  
   391      cmd = [bin, 'backup', 'create', snapshot1,
   392             '--dest', "vfs://" + BACKUP_DEST]
   393      backup1 = subprocess.check_output(cmd).strip()
   394  
   395      cmd = [bin, 'snapshot', 'create']
   396      output = subprocess.check_output(cmd).strip()
   397      snapshot2 = replica_client.list_replica()[0].chain[1]
   398  
   399      assert snapshot2 == 'volume-snap-{}.img'.format(output)
   400  
   401      cmd = [bin, 'backup', 'create', snapshot2,
   402             '--dest', "vfs://" + BACKUP_DEST]
   403      backup2 = subprocess.check_output(cmd).strip()
   404  
   405      cmd = [bin, 'backup', 'inspect', backup1]
   406      data = subprocess.check_output(cmd)
   407      backup1_info = json.loads(data)
   408      assert backup1_info["BackupURL"] == backup1
   409      assert backup1_info["VolumeName"] == VOLUME_NAME
   410      assert backup1_info["VolumeSize"] == VOLUME_SIZE
   411      assert backup1_info["SnapshotName"] == snapshot1
   412  
   413      cmd = [bin, 'backup', 'inspect', backup2]
   414      data = subprocess.check_output(cmd)
   415      backup2_info = json.loads(data)
   416      assert backup2_info["BackupURL"] == backup2
   417      assert backup2_info["VolumeName"] == VOLUME_NAME
   418      assert backup2_info["VolumeSize"] == VOLUME_SIZE
   419      assert backup2_info["SnapshotName"] == snapshot2
   420  
   421      cmd = [bin, 'backup', 'inspect',
   422             "vfs:///tmp/longhorn-backup?backup=backup-1234&volume=test-volume"]
   423      with pytest.raises(subprocess.CalledProcessError) as e:
   424          subprocess.check_call(cmd)
   425          assert 'cannot find' in str(e.value)
   426  
   427      cmd = [bin, 'backup', 'restore', backup1]
   428      subprocess.check_call(cmd)
   429  
   430      cmd = [bin, 'backup', 'restore', backup2]
   431      subprocess.check_call(cmd)
   432  
   433      cmd = [bin, 'backup', 'rm', backup1]
   434      subprocess.check_call(cmd)
   435      cmd = [bin, 'backup', 'rm', backup2]
   436      subprocess.check_call(cmd)
   437  
   438      assert os.path.exists(BACKUP_DEST)
   439  
   440      cmd = [bin, 'backup', 'inspect',
   441             "vfs:///tmp/longhorn-backup?backup=backup-1234&volume=test-volume"]
   442      with pytest.raises(subprocess.CalledProcessError) as e:
   443          subprocess.check_call(cmd)
   444          assert 'cannot find' in str(e.value)
   445  
   446      cmd = [bin, 'backup', 'inspect', "xxx"]
   447      with pytest.raises(subprocess.CalledProcessError) as e:
   448          subprocess.check_call(cmd)
   449          assert 'not supported' in str(e.value)